From ae8f1b7ec34b8a15ca9ebb37edb4421bd5d3b8fd Mon Sep 17 00:00:00 2001 From: Oren Rosen Date: Tue, 29 Nov 2022 11:22:45 +0200 Subject: [PATCH 1/5] Add client --- coolfacts/cmd/coolfacts_client/client.go | 94 ++++++++++++++++++++++++ coolfacts/cmd/coolfacts_client/main.go | 74 +++++++++++++++++++ 2 files changed, 168 insertions(+) create mode 100644 coolfacts/cmd/coolfacts_client/client.go create mode 100644 coolfacts/cmd/coolfacts_client/main.go diff --git a/coolfacts/cmd/coolfacts_client/client.go b/coolfacts/cmd/coolfacts_client/client.go new file mode 100644 index 0000000..5f6a802 --- /dev/null +++ b/coolfacts/cmd/coolfacts_client/client.go @@ -0,0 +1,94 @@ +package main + +import ( + "encoding/json" + "fmt" + "io" + "io/ioutil" + "net/http" + + "github.com/FTBpro/go-workshop/coolfacts/coolfact" +) + +const ( + pathGetFacts = "/facts" +) + +type getFactsResponse struct { + // TODO: add fields + // This struct represent the createFact API response body of the server. + // We will decode the response into a variable of this struct type. + // Since the server response is json, we will use json decode method. + // For this be sure to add json tags on the struct. (https://gobyexample.com/json) + // The response body is: + // { + // "facts": [ + // { + // "image": "...", + // "description": "...", + // "createdAt": "...", + // } + // ... + // ] + // } + // +} + +func (r getFactsResponse) ToCoolFacts() []coolfact.Fact { + // TODO: implement + // loop over the response facts and convert them to the entity type []coolfact.Fact +} + +type client struct { + endpoint string + httpClient *http.Client +} + +func NewClient(endpoint string) *client { + return &client{ + endpoint: endpoint, + httpClient: &http.Client{}, + } +} + +func (c *client) GetAllFacts() ([]coolfact.Fact, error) { + ul := c.endpoint + pathGetFacts + res, err := c.httpClient.Get(ul) + if err != nil { + return nil, fmt.Errorf("client.GetLastCreatedFact to do request: %v", err) + } + + // The client must close the body after the response is handled + // We must read all the body before closing it, so for reading the body and copying to ioutil.Discard, which does nothing + defer func() { + if res != nil && res.Body != nil { + io.Copy(ioutil.Discard, res.Body) + res.Body.Close() + } + }() + + // TODO: handle response + // this method returns *http.Response. + // - If response status code isn't 200 (http.StatusOK), you should read the error from the response. + // use method c.readError which is already implemented. + // - If the response is OK, use method readResponseGetFacts (which you will implement) to return the facts +} + +type errorResponse struct { + Error string `json:"error"` +} + +func (c *client) readError(res *http.Response) (string, error) { + var errRes errorResponse + if err := json.NewDecoder(res.Body).Decode(&errRes); err != nil { + return "", fmt.Errorf("readBody failed to read response body: %v. \nbody string is: %s", err) + } + + return errRes.Error, nil +} + +func (c *client) readResponseGetFacts(res *http.Response) (getFactsResponse, error) { + // TODO: implement - decode the json response into the target + // Use variable of type getFactsResponse. + // Use json.NewDecoder(...).Decode(...) (unlike the decoding in readError method) +} diff --git a/coolfacts/cmd/coolfacts_client/main.go b/coolfacts/cmd/coolfacts_client/main.go new file mode 100644 index 0000000..bcf898f --- /dev/null +++ b/coolfacts/cmd/coolfacts_client/main.go @@ -0,0 +1,74 @@ +package main + +import ( + "bufio" + "errors" + "fmt" + "log" + "os" + "regexp" + "strings" +) + +const ( + serverEndpoint = "http://127.0.0.1:9002" + + commandGetAllFacts = "getAllFact" +) + +func main() { + fmt.Println("Hello, Client!") + + cl := NewClient(serverEndpoint) + + reader := bufio.NewReader(os.Stdin) + for { + fmt.Print("> ") + input, err := reader.ReadString('\n') + if err != nil { + log.Fatal(err) + } + + input = strings.Trim(input, "\n ") + tokens := regexp.MustCompile("[ ]+").Split(input, -1) + + cmd, args := tokens[0], tokens[1:] + if cmd == "exit" { + fmt.Println("Bye, bye!") + return + } + + res, err := processCmd(cl, cmd, args) + if err != nil { + fmt.Println("ERROR:", err) + continue + } + + if res != "" { + fmt.Println(res) + } + } + +} + +func processCmd(cl *client, cmd string, args []string) (string, error) { + switch cmd { + case "": + return "", nil + case commandGetAllFacts: + facts, err := cl.GetAllFacts() + if err != nil { + return "", err + } + + var msg string + for i, fact := range facts { + msg += fmt.Sprintf("\n**************\nFact %d:", i) + msg += fmt.Sprintf("\timage: %s\n\tdescription: %s\n\tcreatedAt: %s", fact.Image, fact.Description) + } + + return msg, nil + default: + return "", errors.New("unknown command") + } +} From 073e1a3cb2ab7995a48b7d36c8dfdf03f8c400fa Mon Sep 17 00:00:00 2001 From: Oren Rosen Date: Fri, 2 Dec 2022 15:18:09 +0200 Subject: [PATCH 2/5] change to topic --- coolfacts/cmd/coolfacts_client/client.go | 3 +-- coolfacts/cmd/coolfacts_client/main.go | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/coolfacts/cmd/coolfacts_client/client.go b/coolfacts/cmd/coolfacts_client/client.go index 5f6a802..946d89a 100644 --- a/coolfacts/cmd/coolfacts_client/client.go +++ b/coolfacts/cmd/coolfacts_client/client.go @@ -24,9 +24,8 @@ type getFactsResponse struct { // { // "facts": [ // { - // "image": "...", + // "topic": "...", // "description": "...", - // "createdAt": "...", // } // ... // ] diff --git a/coolfacts/cmd/coolfacts_client/main.go b/coolfacts/cmd/coolfacts_client/main.go index bcf898f..d1f18d3 100644 --- a/coolfacts/cmd/coolfacts_client/main.go +++ b/coolfacts/cmd/coolfacts_client/main.go @@ -64,7 +64,7 @@ func processCmd(cl *client, cmd string, args []string) (string, error) { var msg string for i, fact := range facts { msg += fmt.Sprintf("\n**************\nFact %d:", i) - msg += fmt.Sprintf("\timage: %s\n\tdescription: %s\n\tcreatedAt: %s", fact.Image, fact.Description) + msg += fmt.Sprintf("\tTopic: %s\n\tDescription: %s\n", fact.Topic, fact.Description) } return msg, nil From b948641074867fabc2030810a225ff7edc983e5a Mon Sep 17 00:00:00 2001 From: Oren Rosen Date: Sat, 10 Dec 2022 12:42:41 +0200 Subject: [PATCH 3/5] rename --- coolfacts/cmd/coolfacts_client/client.go | 2 +- coolfacts/cmd/coolfacts_client/main.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/coolfacts/cmd/coolfacts_client/client.go b/coolfacts/cmd/coolfacts_client/client.go index 946d89a..7679ea5 100644 --- a/coolfacts/cmd/coolfacts_client/client.go +++ b/coolfacts/cmd/coolfacts_client/client.go @@ -50,7 +50,7 @@ func NewClient(endpoint string) *client { } } -func (c *client) GetAllFacts() ([]coolfact.Fact, error) { +func (c *client) GetFacts() ([]coolfact.Fact, error) { ul := c.endpoint + pathGetFacts res, err := c.httpClient.Get(ul) if err != nil { diff --git a/coolfacts/cmd/coolfacts_client/main.go b/coolfacts/cmd/coolfacts_client/main.go index d1f18d3..fa7fbcd 100644 --- a/coolfacts/cmd/coolfacts_client/main.go +++ b/coolfacts/cmd/coolfacts_client/main.go @@ -13,7 +13,7 @@ import ( const ( serverEndpoint = "http://127.0.0.1:9002" - commandGetAllFacts = "getAllFact" + commandGetFacts = "getFacts" ) func main() { @@ -55,8 +55,8 @@ func processCmd(cl *client, cmd string, args []string) (string, error) { switch cmd { case "": return "", nil - case commandGetAllFacts: - facts, err := cl.GetAllFacts() + case commandGetFacts: + facts, err := cl.GetFacts() if err != nil { return "", err } From 7215bf2ac6cbd209ee971f0fc31fc74cb8c34000 Mon Sep 17 00:00:00 2001 From: Oren Rosen Date: Sat, 10 Dec 2022 18:14:37 +0200 Subject: [PATCH 4/5] fix --- coolfacts/cmd/coolfacts_client/client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coolfacts/cmd/coolfacts_client/client.go b/coolfacts/cmd/coolfacts_client/client.go index 7679ea5..ce7cbae 100644 --- a/coolfacts/cmd/coolfacts_client/client.go +++ b/coolfacts/cmd/coolfacts_client/client.go @@ -80,7 +80,7 @@ type errorResponse struct { func (c *client) readError(res *http.Response) (string, error) { var errRes errorResponse if err := json.NewDecoder(res.Body).Decode(&errRes); err != nil { - return "", fmt.Errorf("readBody failed to read response body: %v. \nbody string is: %s", err) + return "", fmt.Errorf("readBody failed to read response body: %v. \n", err) } return errRes.Error, nil From aa6737c44243cd5d22b3442ed1b084b688df5285 Mon Sep 17 00:00:00 2001 From: Oren Rosen Date: Sat, 10 Dec 2022 18:24:20 +0200 Subject: [PATCH 5/5] fix --- coolfacts/cmd/coolfacts_client/client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coolfacts/cmd/coolfacts_client/client.go b/coolfacts/cmd/coolfacts_client/client.go index ce7cbae..b46a4bd 100644 --- a/coolfacts/cmd/coolfacts_client/client.go +++ b/coolfacts/cmd/coolfacts_client/client.go @@ -80,7 +80,7 @@ type errorResponse struct { func (c *client) readError(res *http.Response) (string, error) { var errRes errorResponse if err := json.NewDecoder(res.Body).Decode(&errRes); err != nil { - return "", fmt.Errorf("readBody failed to read response body: %v. \n", err) + return "", fmt.Errorf("readBody failed to read response body: %v", err) } return errRes.Error, nil