diff --git a/docs/doc.md b/docs/doc.md index d1c33b87..c21f756c 100644 --- a/docs/doc.md +++ b/docs/doc.md @@ -6,7 +6,8 @@ - [Build with json replacement](#build-with-json-replacement) - [Build without MsgPack rendering feature](#build-without-msgpack-rendering-feature) - [Routing](#routing) - - [Using GET, POST, PUT, PATCH, DELETE and OPTIONS](#using-get-post-put-patch-delete-and-options) + - [Using GET, POST, PUT, PATCH, QUERY, DELETE and OPTIONS](#using-get-post-put-patch-delete-query-and-options) + - [QUERY Method (RFC 10008)](#query-method-rfc-10008) - [Parameters in path](#parameters-in-path) - [Querystring parameters](#querystring-parameters) - [Multipart/Urlencoded Form](#multiparturlencoded-form) @@ -114,7 +115,7 @@ This is useful to reduce the binary size of executable files. See the [detail in > Learn how to define routes, handle parameters, and organize endpoints. -### Using GET, POST, PUT, PATCH, DELETE and OPTIONS +### Using GET, POST, PUT, PATCH, DELETE, QUERY and OPTIONS ```go func main() { @@ -127,6 +128,7 @@ func main() { router.PUT("/somePut", putting) router.DELETE("/someDelete", deleting) router.PATCH("/somePatch", patching) + router.QUERY("/someQuery", querying) router.HEAD("/someHead", head) router.OPTIONS("/someOptions", options) @@ -136,6 +138,19 @@ func main() { // router.Run(":3000") for a hard coded port } ``` +### QUERY Method (RFC 10008) + +Gin supports the HTTP `QUERY` method defined by RFC 10008. + +```go +router.QUERY("/search", querying) +``` + +The exported `gin.MethodQuery` constant can be used wherever an HTTP method is required, such as when constructing requests: + +```go +req := httptest.NewRequest(gin.MethodQuery, "/query", nil) +``` ### Parameters in path diff --git a/ginS/gins.go b/ginS/gins.go index 7918ce3a..5a82ab09 100644 --- a/ginS/gins.go +++ b/ginS/gins.go @@ -67,6 +67,11 @@ func GET(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes { return engine().GET(relativePath, handlers...) } +// QUERY is a shortcut for router.Handle("QUERY", path, handle) +func QUERY(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes { + return engine().QUERY(relativePath, handlers...) +} + // DELETE is a shortcut for router.Handle("DELETE", path, handle) func DELETE(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes { return engine().DELETE(relativePath, handlers...) diff --git a/ginS/gins_test.go b/ginS/gins_test.go index ffde85d2..d7f0d624 100644 --- a/ginS/gins_test.go +++ b/ginS/gins_test.go @@ -31,6 +31,19 @@ func TestGET(t *testing.T) { assert.Equal(t, "test", w.Body.String()) } +func TestQUERY(t *testing.T) { + QUERY("/query", func(c *gin.Context) { + c.String(http.StatusOK, "query") + }) + + req := httptest.NewRequest(gin.MethodQuery, "/query", nil) + w := httptest.NewRecorder() + engine().ServeHTTP(w, req) + + assert.Equal(t, http.StatusOK, w.Code) + assert.Equal(t, "query", w.Body.String()) +} + func TestPOST(t *testing.T) { POST("/post", func(c *gin.Context) { c.String(http.StatusCreated, "created") diff --git a/routergroup.go b/routergroup.go index c01b917e..1b5c8b0e 100644 --- a/routergroup.go +++ b/routergroup.go @@ -11,6 +11,9 @@ import ( "strings" ) +// MethodQuery is the HTTP QUERY method defined by RFC 10008. +const MethodQuery = "QUERY" + var ( // regEnLetter matches english letters for http method name regEnLetter = regexp.MustCompile("^[A-Z]+$") @@ -19,7 +22,7 @@ var ( anyMethods = []string{ http.MethodGet, http.MethodPost, http.MethodPut, http.MethodPatch, http.MethodHead, http.MethodOptions, http.MethodDelete, http.MethodConnect, - http.MethodTrace, + http.MethodTrace, MethodQuery, } ) @@ -36,6 +39,7 @@ type IRoutes interface { Handle(string, string, ...HandlerFunc) IRoutes Any(string, ...HandlerFunc) IRoutes GET(string, ...HandlerFunc) IRoutes + QUERY(string, ...HandlerFunc) IRoutes POST(string, ...HandlerFunc) IRoutes DELETE(string, ...HandlerFunc) IRoutes PATCH(string, ...HandlerFunc) IRoutes @@ -117,6 +121,11 @@ func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRou return group.handle(http.MethodGet, relativePath, handlers) } +// QUERY is a shortcut for router.Handle("QUERY", path, handlers). +func (group *RouterGroup) QUERY(relativePath string, handlers ...HandlerFunc) IRoutes { + return group.handle(MethodQuery, relativePath, handlers) +} + // DELETE is a shortcut for router.Handle("DELETE", path, handlers). func (group *RouterGroup) DELETE(relativePath string, handlers ...HandlerFunc) IRoutes { return group.handle(http.MethodDelete, relativePath, handlers) @@ -143,7 +152,7 @@ func (group *RouterGroup) HEAD(relativePath string, handlers ...HandlerFunc) IRo } // Any registers a route that matches all the HTTP methods. -// GET, POST, PUT, PATCH, HEAD, OPTIONS, DELETE, CONNECT, TRACE. +// GET, POST, PUT, PATCH, HEAD, OPTIONS, DELETE, CONNECT, TRACE, QUERY. func (group *RouterGroup) Any(relativePath string, handlers ...HandlerFunc) IRoutes { for _, method := range anyMethods { group.handle(method, relativePath, handlers) diff --git a/routergroup_test.go b/routergroup_test.go index 182c5589..6c7cf20b 100644 --- a/routergroup_test.go +++ b/routergroup_test.go @@ -42,6 +42,7 @@ func TestRouterGroupBasicHandle(t *testing.T) { performRequestInGroup(t, http.MethodDelete) performRequestInGroup(t, http.MethodHead) performRequestInGroup(t, http.MethodOptions) + performRequestInGroup(t, MethodQuery) } func performRequestInGroup(t *testing.T, method string) { @@ -78,6 +79,9 @@ func performRequestInGroup(t *testing.T, method string) { case http.MethodOptions: v1.OPTIONS("/test", handler) login.OPTIONS("/test", handler) + case MethodQuery: + v1.QUERY("/test", handler) + login.QUERY("/test", handler) default: panic("unknown method") } @@ -182,6 +186,7 @@ func testRoutesInterface(t *testing.T, r IRoutes) { assert.Equal(t, r, r.Handle(http.MethodGet, "/handler", handler)) assert.Equal(t, r, r.Any("/any", handler)) assert.Equal(t, r, r.GET("/", handler)) + assert.Equal(t, r, r.QUERY("/", handler)) assert.Equal(t, r, r.POST("/", handler)) assert.Equal(t, r, r.DELETE("/", handler)) assert.Equal(t, r, r.PATCH("/", handler)) diff --git a/routes_test.go b/routes_test.go index 1cae3fce..9c40cc34 100644 --- a/routes_test.go +++ b/routes_test.go @@ -116,6 +116,7 @@ func TestRouterGroupRouteOK(t *testing.T) { testRouteOK(http.MethodDelete, t) testRouteOK(http.MethodConnect, t) testRouteOK(http.MethodTrace, t) + testRouteOK(MethodQuery, t) } func TestRouteNotOK(t *testing.T) { @@ -128,6 +129,7 @@ func TestRouteNotOK(t *testing.T) { testRouteNotOK(http.MethodDelete, t) testRouteNotOK(http.MethodConnect, t) testRouteNotOK(http.MethodTrace, t) + testRouteNotOK(MethodQuery, t) } func TestRouteNotOK2(t *testing.T) { @@ -140,6 +142,7 @@ func TestRouteNotOK2(t *testing.T) { testRouteNotOK2(http.MethodDelete, t) testRouteNotOK2(http.MethodConnect, t) testRouteNotOK2(http.MethodTrace, t) + testRouteNotOK2(MethodQuery, t) } func TestRouteRedirectTrailingSlash(t *testing.T) {