From 1223a7364acfd61265fe6d3e74f3b58518d63064 Mon Sep 17 00:00:00 2001 From: Bill Mill <bill@billmill.org> Date: Sun, 18 Jun 2023 09:34:35 -0400 Subject: [PATCH] feat: add method property to responses (#123) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ```console # before: httpbingo lacks the "method" field but httpbin.org has it $ curl -s https://httpbingo.org/anything | jq .method  9:31PM null $ curl -s https://httpbin.org/anything | jq .method "GET" # after: httpbingo has the method field! $ curl -s http://0.0.0.0:8080/anything | jq .method "GET" ``` This was mentioned in #6, but then not listed in #91 - I took the highly technical testing approach of adding a test for `Method` anywhere in `handlers_test.go` that mentioned `Args`; do you desire more tests? fewer tests? - Anywhere else I should add this field that I didn't already? For what it's worth, I discovered this when working on upgrading the testing for our [httpsnippet library](https://github.com/readmeio/httpsnippet); I wanted to use `go-httpbin` but our tests expect the method field to be present in the responses --- httpbin/handlers.go | 5 +++++ httpbin/handlers_test.go | 32 ++++++++++++++++++++++++++++++++ httpbin/responses.go | 2 ++ 3 files changed, 39 insertions(+) diff --git a/httpbin/handlers.go b/httpbin/handlers.go index 536d271..a15a8a6 100644 --- a/httpbin/handlers.go +++ b/httpbin/handlers.go @@ -47,6 +47,7 @@ func (h *HTTPBin) Get(w http.ResponseWriter, r *http.Request) { writeJSON(http.StatusOK, w, &noBodyResponse{ Args: r.URL.Query(), Headers: getRequestHeaders(r), + Method: r.Method, Origin: getClientIP(r), URL: getURL(r).String(), }) @@ -71,6 +72,7 @@ func (h *HTTPBin) RequestWithBody(w http.ResponseWriter, r *http.Request) { resp := &bodyResponse{ Args: r.URL.Query(), Headers: getRequestHeaders(r), + Method: r.Method, Origin: getClientIP(r), URL: getURL(r).String(), } @@ -93,6 +95,7 @@ func (h *HTTPBin) Gzip(w http.ResponseWriter, r *http.Request) { mustMarshalJSON(gzw, &noBodyResponse{ Args: r.URL.Query(), Headers: getRequestHeaders(r), + Method: r.Method, Origin: getClientIP(r), Gzipped: true, }) @@ -115,6 +118,7 @@ func (h *HTTPBin) Deflate(w http.ResponseWriter, r *http.Request) { mustMarshalJSON(zw, &noBodyResponse{ Args: r.URL.Query(), Headers: getRequestHeaders(r), + Method: r.Method, Origin: getClientIP(r), Deflated: true, }) @@ -749,6 +753,7 @@ func (h *HTTPBin) ETag(w http.ResponseWriter, r *http.Request) { mustMarshalJSON(&buf, noBodyResponse{ Args: r.URL.Query(), Headers: getRequestHeaders(r), + Method: r.Method, Origin: getClientIP(r), URL: getURL(r).String(), }) diff --git a/httpbin/handlers_test.go b/httpbin/handlers_test.go index 1fd1c2b..b54c904 100644 --- a/httpbin/handlers_test.go +++ b/httpbin/handlers_test.go @@ -150,6 +150,9 @@ func TestGet(t *testing.T) { if resp.Args.Encode() != "" { t.Fatalf("expected empty args, got %s", resp.Args.Encode()) } + if resp.Method != "GET" { + t.Fatalf("expected method to be GET, got %s", resp.Method) + } if resp.Origin != "" { t.Fatalf("expected empty origin, got %#v", resp.Origin) } @@ -179,6 +182,9 @@ func TestGet(t *testing.T) { if resp.Args.Encode() != params.Encode() { t.Fatalf("args mismatch: %s != %s", resp.Args.Encode(), params.Encode()) } + if resp.Method != "GET" { + t.Fatalf("expected method to be GET, got %s", resp.Method) + } }) t.Run("only_allows_gets", func(t *testing.T) { @@ -601,6 +607,9 @@ func testRequestWithBodyBinaryBody(t *testing.T, verb string, path string) { if len(resp.Args) > 0 { t.Fatalf("expected no query params, got %#v", resp.Args) } + if resp.Method != verb { + t.Fatalf("expected method to be %s, got %s", verb, resp.Method) + } if len(resp.Form) > 0 { t.Fatalf("expected no form data, got %#v", resp.Form) } @@ -645,6 +654,9 @@ func testRequestWithBodyEmptyBody(t *testing.T, verb string, path string) { if len(resp.Args) > 0 { t.Fatalf("expected no query params, got %#v", resp.Args) } + if resp.Method != verb { + t.Fatalf("expected method to be %s, got %s", verb, resp.Method) + } if len(resp.Form) > 0 { t.Fatalf("expected no form data, got %#v", resp.Form) } @@ -675,6 +687,9 @@ func testRequestWithBodyFormEncodedBody(t *testing.T, verb, path string) { if len(resp.Args) > 0 { t.Fatalf("expected no query params, got %#v", resp.Args) } + if resp.Method != verb { + t.Fatalf("expected method to be %s, got %s", verb, resp.Method) + } if len(resp.Form) != len(params) { t.Fatalf("expected %d form values, got %d", len(params), len(resp.Form)) } @@ -731,6 +746,9 @@ func testRequestWithBodyFormEncodedBodyNoContentType(t *testing.T, verb, path st if len(resp.Args) > 0 { t.Fatalf("expected no query params, got %#v", resp.Args) } + if resp.Method != verb { + t.Fatalf("expected method to be %s, got %s", verb, resp.Method) + } if len(resp.Form) != 0 { t.Fatalf("expected no form values, got %d", len(resp.Form)) } @@ -781,6 +799,9 @@ func testRequestWithBodyMultiPartBody(t *testing.T, verb, path string) { if len(resp.Args) > 0 { t.Fatalf("expected no query params, got %#v", resp.Args) } + if resp.Method != verb { + t.Fatalf("expected method to be %s, got %s", verb, resp.Method) + } if len(resp.Form) != len(params) { t.Fatalf("expected %d form values, got %d", len(params), len(resp.Form)) } @@ -846,6 +867,9 @@ func testRequestWithBodyJSON(t *testing.T, verb, path string) { if len(resp.Args) > 0 { t.Fatalf("expected no query params, got %#v", resp.Args) } + if resp.Method != verb { + t.Fatalf("expected method to be %s, got %s", verb, resp.Method) + } if len(resp.Form) != 0 { t.Fatalf("expected no form values, got %d", len(resp.Form)) } @@ -905,6 +929,10 @@ func testRequestWithBodyQueryParams(t *testing.T, verb, path string) { t.Fatalf("expected args = %#v in response, got %#v", params.Encode(), resp.Args.Encode()) } + if resp.Method != "POST" { + t.Fatalf("expected method to be POST, got %s", resp.Method) + } + if len(resp.Form) > 0 { t.Fatalf("expected form data, got %#v", resp.Form) } @@ -942,6 +970,10 @@ func testRequestWithBodyQueryParamsAndBody(t *testing.T, verb, path string) { t.Fatalf("expected args = %#v in response, got %#v", args.Encode(), resp.Args.Encode()) } + if resp.Method != "POST" { + t.Fatalf("expected method to be POST, got %s", resp.Method) + } + if len(resp.Form) != len(form) { t.Fatalf("expected %d form values, got %d", len(form), len(resp.Form)) } diff --git a/httpbin/responses.go b/httpbin/responses.go index 66790a4..ad08fca 100644 --- a/httpbin/responses.go +++ b/httpbin/responses.go @@ -27,6 +27,7 @@ type userAgentResponse struct { type noBodyResponse struct { Args url.Values `json:"args"` Headers http.Header `json:"headers"` + Method string `json:"method"` Origin string `json:"origin"` URL string `json:"url"` @@ -39,6 +40,7 @@ type noBodyResponse struct { type bodyResponse struct { Args url.Values `json:"args"` Headers http.Header `json:"headers"` + Method string `json:"method"` Origin string `json:"origin"` URL string `json:"url"` -- GitLab