Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(kvstore API): Implement /api/get with HTTP GET #30

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
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
18 changes: 10 additions & 8 deletions 99-labs/04-immutability/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Cloud native apps are, in contrast, stateless, storing all *resource state* in a
Version int `json:"version"`
}
```
- `POST /api/get, body: "key"`: get versioned value for the key given in the HTTP request body;
- `GET /api/get?id=<id> `: get versioned value for the key given in the query parameter with the name id;
- `POST /api/put, body: {"key":<key>, "value":<value>, "version":<version>}`: insert the key-value pair into the database (only if the current version equals the specified version);
- `GET /api/reset`: remove all key-value pairs from the store; and
- `GET /api/list`: list the stored versioned key-value pairs.
Expand All @@ -86,7 +86,7 @@ Make sure to familiarize yourself with the workings of `kvstore`:
```
- query the currently stored value and version in the database for `key1`:
```shell
curl -X POST -H "Content-Type: application/json" --data '"key1"' http://localhost:8081/api/get
curl -X GET http://localhost:8081/api/get?id=key1
{"value":"1","version":1}
```
- insert the new value with the new version and then list the entire content of the database:
Expand Down Expand Up @@ -177,18 +177,20 @@ Your task is to implement this interface. Some help:
4. At this point, we are ready to actually implement the `Client` interface. Let us add the implementation for the `get` method first; recall, this receives a string key as an argument and returns the corresponding key and version as an `api.VersionedValue`:
``` go
// Get returns the value and version stored for the given key, or an error if something goes wrong.
func (c *client) Get(key string) (api.VersionedValue, error) {
// this will package the requested key into the body of the HTTP request
body := []byte(fmt.Sprintf("\"%s\"", key))

func (c *client) Get(key string) (api.VersionedValue, error) {
//this will append the query parameter formatted to the url
uri, _ := url.Parse(c.url + "/api/get")
q := uri.Query()
q.Set("id", key)
uri.RawQuery = q.Encode()
...
}
```

The function itself will have to perform the following steps:
- make a HTTP POST call to the HTTP server at the URL `c.url` (`c` is the receiver of the `Get` function of our implementation type `client`) at the API endpoint `/api/get`:
- make a HTTP GET call to the HTTP server at the URL `c.url` (`c` is the receiver of the `Get` function of our implementation type `client`) at the API endpoint `/api/get` using the `key` argument as the query id parameter value:
```go
r, err := http.Post(c.url+"/api/get", "application/json", bytes.NewReader(body))
r, err := http.Get(uri.String())
```
- return an empty `api.VersionedValue{}` and an error if something goes wrong,
- check if the return status is 200 (`http.StatusOK`) and return an empty `api.VersionedValue{}` and an error if not,
Expand Down
13 changes: 7 additions & 6 deletions 99-labs/code/kvstore/pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,17 @@ func NewServer(logFile string) (*Server, error) {
})

http.HandleFunc("/api/get", func(w http.ResponseWriter, r *http.Request) {
key := ""
defer r.Body.Close()
if err := json.NewDecoder(r.Body).Decode(&key); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
//Enforce HTTP GET on the GET endpoint
if r.Method != "GET" {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
if key == "" {
w.WriteHeader(http.StatusBadRequest)
params := r.URL.Query()
if !params.Has("id") {
http.Error(w, "No transaction id supplied as query parameter", http.StatusBadRequest)
return
}
key := params.Get("id")
log.Printf("get: key=%s\n", key)
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(s.get(key))
Expand Down
Loading