diff --git a/httpbin/handlers.go b/httpbin/handlers.go index 1fe6b7e50fc9e87b788d5c87827de95d3081cc41..be4a018987eb547e5e49b14bea4e2b6218fba3c8 100644 --- a/httpbin/handlers.go +++ b/httpbin/handlers.go @@ -7,6 +7,7 @@ import ( "encoding/json" "fmt" "net/http" + "net/http/httputil" "net/url" "sort" "strconv" @@ -1013,6 +1014,20 @@ func (h *HTTPBin) Base64(w http.ResponseWriter, r *http.Request) { writeResponse(w, http.StatusOK, "text/plain", result) } +// DumpRequest - returns the given request in its HTTP/1.x wire representation. +// The returned representation is an approximation only; +// some details of the initial request are lost while parsing it into +// an http.Request. In particular, the order and case of header field +// names are lost. +func (h *HTTPBin) DumpRequest(w http.ResponseWriter, r *http.Request) { + dump, err := httputil.DumpRequest(r, true) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + w.Write(dump) +} + // JSON - returns a sample json func (h *HTTPBin) JSON(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", jsonContentType) diff --git a/httpbin/handlers_test.go b/httpbin/handlers_test.go index 7c3064a7c4f9ea15f5538a59fe37d258263ff4b3..07a5e4af9c603a33358f16527842dd0de5d93e3a 100644 --- a/httpbin/handlers_test.go +++ b/httpbin/handlers_test.go @@ -2840,6 +2840,19 @@ func TestBase64(t *testing.T) { } } +func TestDumpRequest(t *testing.T) { + t.Parallel() + r, _ := http.NewRequest("GET", "/dump/request?foo=bar", nil) + r.Host = "test-host" + r.Header.Set("x-test-header2", "Test-Value2") + r.Header.Set("x-test-header1", "Test-Value1") + w := httptest.NewRecorder() + app.ServeHTTP(w, r) + + assertContentType(t, w, "text/plain; charset=utf-8") + assertBodyEquals(t, w, "GET /dump/request?foo=bar HTTP/1.1\r\nHost: test-host\r\nX-Test-Header1: Test-Value1\r\nX-Test-Header2: Test-Value2\r\n\r\n") +} + func TestJSON(t *testing.T) { t.Parallel() r, _ := http.NewRequest("GET", "/json", nil) diff --git a/httpbin/httpbin.go b/httpbin/httpbin.go index 2a48d4d499115780a4dee73b627d7563146c18fc..3f0f4a4a679449e478779c26c94fac2323008169 100644 --- a/httpbin/httpbin.go +++ b/httpbin/httpbin.go @@ -145,6 +145,8 @@ func (h *HTTPBin) Handler() http.Handler { mux.HandleFunc("/uuid", h.UUID) mux.HandleFunc("/base64/", h.Base64) + mux.HandleFunc("/dump/request", h.DumpRequest) + // existing httpbin endpoints that we do not support mux.HandleFunc("/brotli", notImplementedHandler) diff --git a/httpbin/static/index.html b/httpbin/static/index.html index f19820baa4b95e70989a4e51be1a43a737f0e696..4d94d0b5c7dab3f612bd05b121526bbd79bf72d8 100644 --- a/httpbin/static/index.html +++ b/httpbin/static/index.html @@ -80,6 +80,7 @@ <li><a href="/digest-auth/auth/user/passwd/MD5"><code>/digest-auth/:qop/:user/:passwd/:algorithm</code></a> Challenges HTTP Digest Auth.</li> <li><a href="/digest-auth/auth/user/passwd/MD5"><code>/digest-auth/:qop/:user/:passwd</code></a> Challenges HTTP Digest Auth.</li> <li><a href="/drip?code=200&numbytes=5&duration=5"><code>/drip?numbytes=n&duration=s&delay=s&code=code</code></a> Drips data over a duration after an optional initial delay, then (optionally) returns with the given status code.</li> +<li><a href="/dump/request"><code>/dump/request</code></a> Returns the given request in its HTTP/1.x wire approximate representation.</li> <li><a href="/encoding/utf8"><code>/encoding/utf8</code></a> Returns page containing UTF-8 data.</li> <li><a href="/etag/etag"><code>/etag/:etag</code></a> Assumes the resource has the given etag and responds to If-None-Match header with a 200 or 304 and If-Match with a 200 or 412 as appropriate.</li> <li><a href="/forms/post"><code>/forms/post</code></a> HTML form that submits to <em>/post</em></li> @@ -158,6 +159,14 @@ } </code></pre> +<h3 id="-curl-http-httpbin-org-dump-request">$ curl https://httpbingo.org/dump/request?foo=bar</h3> + +<pre><code>GET /dump/request?foo=bar HTTP/1.1 +Host: httpbingo.org +Accept: */* +User-Agent: curl/7.64.1 +</code></pre> + <h3 id="-curl-I-http-httpbin-org-status-418">$ curl -I https://httpbingo.org/status/418</h3> <pre><code>HTTP/1.1 418 I'm a teapot