Skip to content

Commit dc216b8

Browse files
committed
route: add support for the QUERY HTTP method
QUERY is a safe, idempotent method that carries a request body (RFC 10008). It is not yet part of net/http, so register it using a locally defined MethodQuery constant. Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
1 parent 1b2cb09 commit dc216b8

2 files changed

Lines changed: 36 additions & 0 deletions

File tree

route/route.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ import (
2020
"github.com/julienschmidt/httprouter"
2121
)
2222

23+
// MethodQuery is the QUERY HTTP method. It is a safe, idempotent method that
24+
// carries a request body, see https://datatracker.ietf.org/doc/rfc10008/.
25+
// It is not yet part of net/http, so it is defined here.
26+
const MethodQuery = "QUERY"
27+
2328
type param string
2429

2530
// Param returns param p for the context, or the empty string when
@@ -114,6 +119,11 @@ func (r *Router) Head(path string, h http.HandlerFunc) {
114119
r.rtr.HEAD(r.prefix+path, r.handle(path, h))
115120
}
116121

122+
// Query registers a new QUERY route.
123+
func (r *Router) Query(path string, h http.HandlerFunc) {
124+
r.rtr.Handle(MethodQuery, r.prefix+path, r.handle(path, h))
125+
}
126+
117127
// Redirect takes an absolute path and sends an internal HTTP redirect for it,
118128
// prefixed by the router's path prefix. Note that this method does not include
119129
// functionality for handling relative paths or full URL redirects.

route/route_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
package route
1515

1616
import (
17+
"io"
1718
"net/http"
1819
"net/http/httptest"
20+
"strings"
1921
"testing"
2022

2123
"github.com/stretchr/testify/require"
@@ -90,6 +92,30 @@ func TestContextWithoutValue(t *testing.T) {
9092
router.ServeHTTP(nil, r)
9193
}
9294

95+
func TestQuery(t *testing.T) {
96+
router := New()
97+
const body = "query=up"
98+
called := false
99+
router.Query("/test/:foo/", func(w http.ResponseWriter, r *http.Request) {
100+
called = true
101+
want := "bar"
102+
got := Param(r.Context(), "foo")
103+
require.Equalf(t, want, got, "Unexpected context value: want %q, got %q", want, got)
104+
105+
gotBody, err := io.ReadAll(r.Body)
106+
require.NoError(t, err)
107+
require.Equal(t, body, string(gotBody))
108+
w.WriteHeader(http.StatusOK)
109+
})
110+
111+
w := httptest.NewRecorder()
112+
r, err := http.NewRequest(MethodQuery, "http://localhost:9090/test/bar/", strings.NewReader(body))
113+
require.NoErrorf(t, err, "Error building test request: %s", err)
114+
router.ServeHTTP(w, r)
115+
require.Truef(t, called, "QUERY handler was not called")
116+
require.Equal(t, http.StatusOK, w.Code)
117+
}
118+
93119
func TestInstrumentation(t *testing.T) {
94120
var got string
95121
cases := []struct {

0 commit comments

Comments
 (0)