Sending Type-safe HTTP Requests With Go | by Kevin Wan | May, 2022

See how the httpc bundle in go-zero is used for sort security.

For Gophers, we principally write code for purchasers to request. Typically we have to request RESTful APIs supplied by third events. Right now, we really feel that it’s laborious to assemble the requests, not troublesome, however error-prone.

For instance, if we need to ship a request like this, it seems to be quite simple, nevertheless it’s nonetheless tedious to truly write it.

POST /articles/5/replace?system=ios HTTP/1.1
Host: go-zero.dev
Authorization: Bearer <jwt-token>
"writer": "kevin", "physique": "this isn't essential!", "title": "my title", "sort":6

This API is definitely fairly easy and we will write it straight from scratch.

func foremost() 
var buf bytes.
encoder := json.NewEncoder(&buf)
params := map[string]interface
"title": "my title",
"physique": "this isn't essential!",
"writer": "kevin",
"sort": 6,

if err := encoder.Encode(params); err ! = nil
fmt.Fprintln(os.Stderr, err)
return
url := fmt.Sprintf("http://go-zero.dev/articles/%d/replace?system=%s", 5, "ios")
req, err := http.NewRequest(http.MethodPost, url, &buf)
if err ! = nil
fmt.Fprintln(os.Stderr, err)
return
req.Header.Add("Authorization", "Bearer <jwt-token>")
cli := http.Shopper
resp, err := cli.Do(req)
if err ! = nil
fmt.Fprintln(os.Stderr, err)
return
io.Copy(os.Stdout, resp.Physique)

We ran a check and located that we didn’t get 200 OK, dumped the packet and the request seems to be as follows. Are you able to consider the explanation for the failure?

POST /articles/5/replace?system=ios HTTP/1.1
Host: go-zero.dev
Consumer-Agent: Go-http-client/1.1
Content material-Size: 79
Authorization: Bearer <jwt-token>
Settle for-Encoding: gzip
"writer": "kevin", "physique": "this isn't essential!", "title": "my title", "sort":6

The precise causes for the failure shall be mentioned under, so let’s clarify this code first. You possibly can see that the map[string]interface is used for the splicing parameters, for every subject we won’t verify if the sort matches. Solely after we ship it out and obtain 200 OK from the server, we will verify that it’s handed accurately. For instance, the sort parameter is used right here as int sort, we might write it as string sort by mistake. However it’s nonetheless laborious to search out out that this parameter is written incorrectly with out requesting it.

So let’s see how the httpc bundle in go-zero is used for sort security.

Let’s see how the code for requesting with the httpc bundle is written.

const url = "http://go-zero.dev/articles/:id/replace"sort UpdateArticle struct 
ID int `path: "id"`
Machine string `kind: "system,choices=ios,android,internet,desktop"`
Authorization string `header: "Authorization"`
Title string `json: "title"`
Physique string `json: "physique"`
Writer string `json: "writer"`
Kind int `json: "sort"`
func foremost()
information := &UpdateArticle
ID: 5,
Machine: "ios",
Authorization: "Bearer <jwt-token>",
Title: "my title",
Physique: "this isn't essential!",
Writer: "kevin",
Kind: 6,
resp, err := httpc.Do(context.Background(), http.MethodPost, url, information)
if err ! = nil
fmt.Fprintln(os.Stderr, err)
return
io.Copy(os.Stdout, resp.Physique)

Let’s confirm the code by sending a request, the result’s as anticipated.

POST /articles/5/replace?system=ios HTTP/1.1
Host: go-zero.dev
Consumer-Agent: Go-http-client/1.1
Content material-Size: 79
Content material-Kind: utility/json; charset=utf-8
Authorization: Bearer <jwt-token>
Settle for-Encoding: gzip
"writer": "kevin", "physique": "this isn't essential!", "title": "my title", "sort":6

Did you discover out that, in distinction to the earlier one, there’s yet one more header was set, Content material-Kind: utility/json; charset=utf-8, and we forgot to set Content material-Kind within the earlier code.

httpc implementation could be very straightforward to know by defining the kind of the request and sending with Do. With help for path, kind, header and json as proven in our code, it is extremely straightforward and type-safe to ship HTTP requests.

Along with the benefit of use and type-safety proven above, the httpc bundle has the next options.

  1. timeout management with context. You possibly can move ctx for the requests.
  2. computerized integration of OpenTelemetry. The trace-id, span-id returned by the server shall be routinely written within the log, in order that the consumer and server can work collectively to research the issues.
  3. use httpc.Service to get the circuit breaker capability. When the server aspect has issues, it would routinely cease sending the requests, to keep away from ineffective requests and scale back the strain on the server aspect.
Wish to Join?You are welcome to make use of go-zero and star to help us!

More Posts