feat: add support for HTTP QUERY method

feat: add support for HTTP QUERY method
This commit is contained in:
Aum Patel 2026-07-05 15:09:50 +05:30
parent 34dac209ff
commit 26ec1613cb
6 changed files with 40 additions and 4 deletions

View File

@ -6,7 +6,7 @@
- [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)
- [Parameters in path](#parameters-in-path)
- [Querystring parameters](#querystring-parameters)
- [Multipart/Urlencoded Form](#multiparturlencoded-form)
@ -114,7 +114,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 +127,7 @@ func main() {
router.PUT("/somePut", putting)
router.DELETE("/someDelete", deleting)
router.PATCH("/somePatch", patching)
router.QUERY("/somePatch", querying)
router.HEAD("/someHead", head)
router.OPTIONS("/someOptions", options)

View File

@ -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...)

View File

@ -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")

View File

@ -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)

View File

@ -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))

View File

@ -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) {