Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,8 @@ jobs:
- name: Check out code into the Go module directory
uses: actions/checkout@v4

- name: Vet
run: go vet ./...

- name: Build
run: go build -v .
run: make build

- name: Test
run: go test -v -cover ./...
run: make test
15 changes: 15 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
fmt:
go fmt ./...

vet:
go vet ./...
test:
go test -v -cover ./...

build:
go build -v .

client:
@go build ./tools/client.go

.PHONY: client
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,29 @@ _Success code_: ```200```
_Error code_: ```400```, empty key is provided.
_Note_: TTL is reset for any subsequent requests for the same key.

```sh
# setting new/updating existing key
curl -X POST http://localhost:8080/key/foo -H 'Content-Type: application/x-www-form-urlencoded' -d 'value=bar'
```

## Getting value by its key
_HTTP method_: ```GET```
_Request's parameter name_: no parameter is needed.
_Success code_: ```200```, response's body contains string value for the key.
_Error code_: ```404```, key is not found in the storage.

```sh
# getting value for existing key
curl http://localhost:8080/key/foo
bar
```

```sh
# an attempt to get value for unknown key
curl http://localhost:8080/key/xyz
404 There is no record in the storage for key 'xyz'.
```

## Deleting value by its key
_HTTP method_: ```POST```
_Request's parameter name_: no parameter is needed.
Expand All @@ -55,6 +72,17 @@ _Error code_: ```404```, key is not found in the storage.

When error is occured code ```400``` is returned by server.

```sh
# deleting existing key
curl -X POST http://localhost:8080/key/foo
```

```sh
# an attempt to delete unknown key
curl -X POST http://localhost:8080/key/xyz
404 There is no record in the storage for key '%v'.
```

# Tests
Run ```go test -v -cover -count=1 ./...```.

Expand Down
50 changes: 29 additions & 21 deletions router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,6 @@ const (
firstPart = "key"
)

var httpStatusCodeMessages = map[int]string{
200: "",
400: "400 Malformed request.\n",
404: "404 There is no record in the storage for key '%v'.\n",
500: "500 Internal storage error.\n",
}

// GetURLrouter - возвращает функцию маршрутизатор HTTP запросов в зависимости от типа.
func GetURLrouter(stor readerWriter) func(
w http.ResponseWriter, r *http.Request,
Expand All @@ -42,14 +35,14 @@ func GetURLrouter(stor readerWriter) func(
return func(w http.ResponseWriter, r *http.Request) {
keyName, ok := getKeyFromURL(r.URL.Path)
if !ok {
w.WriteHeader(400) // Bad request
fmt.Fprint(w, httpStatusCodeMessages[400])
w.WriteHeader(http.StatusBadRequest) // Bad request
fmt.Fprint(w, getMessage(http.StatusBadRequest, ""))
return
}
reqHandler, isHandlerExists := requestFactory(r.Method)
if !isHandlerExists {
w.WriteHeader(400) // Bad request
fmt.Fprint(w, httpStatusCodeMessages[400])
w.WriteHeader(http.StatusBadRequest) // Bad request
fmt.Fprint(w, getMessage(http.StatusBadRequest, ""))
return
}
val, code := reqHandler(stor, keyName, r)
Expand Down Expand Up @@ -88,12 +81,12 @@ func methodGET(stor readerWriter, key string, r *http.Request) (string, int) {
// get the value by its key
val, err := stor.Get(key)
if err != nil {
return httpStatusCodeMessages[500], 500
return getMessage(http.StatusInternalServerError, key), http.StatusInternalServerError
}
if val == nil {
// either error occurred or key is not found in the storage (code 404)
code = 404
val = []byte(fmt.Sprintf(httpStatusCodeMessages[code], key))
code = http.StatusNotFound
val = []byte(getMessage(http.StatusNotFound, key))
}
return string(val), code
}
Expand All @@ -103,7 +96,7 @@ func methodPOST(stor readerWriter, key string, r *http.Request) (string, int) {
value := r.PostFormValue(valueFormFieldName)
postProcessingMethod := postMethodFactory(len(r.Form))
httpCode := postProcessingMethod(stor, key, value)
return httpStatusCodeMessages[httpCode], httpCode
return getMessage(httpCode, key), httpCode
}

func postMethodFactory(formLen int) func(storage readerWriter, key, value string) int {
Expand All @@ -121,25 +114,40 @@ func deleteElementRequest(storage readerWriter, key, value string) int {
delStatus, err := storage.Delete(key)
if err != nil {
// something went wrong with the storage
return 500
return http.StatusInternalServerError
}
if delStatus {
// element deleted successfully
return 200
return http.StatusOK
}
// element was not found and is not deleted
return 404
return http.StatusNotFound
}

func setElementRequest(storage readerWriter, key, value string) int {
// setting (updating) the value by its key
err := storage.Set(key, value)
if err != nil {
// something went wrong with the storage
return 500
return http.StatusInternalServerError
}
if value != "" {
return 200
return http.StatusOK
}
return http.StatusBadRequest
}

func getMessage(code int, key string) string {
switch code {
case http.StatusOK:
return ""
case http.StatusBadRequest:
return "Malformed request"
case http.StatusNotFound:
return fmt.Sprintf("There is no record in the storage for key '%v'", key)
case http.StatusInternalServerError:
return "Internal storage error"
default:
return ""
}
return 400
}
37 changes: 23 additions & 14 deletions router/router_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ func Test_getKeyFromURL(t *testing.T) {

type myResponseWriter struct {
code int
msg []byte
}

func (resp *myResponseWriter) Header() http.Header {
Expand All @@ -125,8 +126,8 @@ func (resp *myResponseWriter) WriteHeader(code int) {
}

func (resp *myResponseWriter) Write(inp []byte) (int, error) {
var er error
return int(1), er
resp.msg = inp
return len(inp), nil
}

func (resp *myResponseWriter) getCode() int {
Expand Down Expand Up @@ -156,10 +157,11 @@ func Test_closure(t *testing.T) {
r *http.Request
}
tests := []struct {
name string
args args
want int // код ошибки
text string
name string
args args
want int // код ошибки
errMsg string // error text
text string
}{
{
name: "Incorrect HTTP method (verb)",
Expand All @@ -174,7 +176,8 @@ func Test_closure(t *testing.T) {
},
},
},
want: 400,
want: 400,
errMsg: "Malformed request",
},
{
name: "Getting value from the empty storage",
Expand All @@ -189,7 +192,8 @@ func Test_closure(t *testing.T) {
},
},
},
want: 404,
want: 404,
errMsg: "There is no record in the storage for key 'key1'",
},
{
name: "Deleting from the empty storage",
Expand All @@ -204,7 +208,8 @@ func Test_closure(t *testing.T) {
},
},
},
want: 404,
want: 404,
errMsg: "There is no record in the storage for key '" + correctKey + "'",
},
{
name: "Setting value with empty key",
Expand All @@ -219,7 +224,8 @@ func Test_closure(t *testing.T) {
},
},
},
want: 400,
want: 400,
errMsg: "Malformed request",
},
{
name: "URL keyword is incorrect",
Expand All @@ -234,7 +240,8 @@ func Test_closure(t *testing.T) {
},
},
},
want: 400,
want: 400,
errMsg: "Malformed request",
},
{
name: "Correct setting the value by its key",
Expand Down Expand Up @@ -265,7 +272,8 @@ func Test_closure(t *testing.T) {
w: writer,
r: reqBad,
},
want: 400,
want: 400,
errMsg: "Malformed request",
},
}
for _, tt := range tests {
Expand All @@ -275,8 +283,9 @@ func Test_closure(t *testing.T) {

handler(tt.args.w, tt.args.r)
got := writer.getCode()
if got != tt.want {
t.Errorf("urlHandler() got = %v, want %v", got, tt.want)
msg := writer.msg
if got != tt.want || string(msg) != tt.errMsg {
t.Errorf("GetURLrouter() got = %v, want %v", got, tt.want)
}
})
}
Expand Down
Loading
Loading