Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,7 @@ const (
methodOptions
methodTrace
methodPatch
methodQuery
)

// HTTP methods enabled by default
Expand All @@ -612,6 +613,7 @@ var DefaultMethods = []string{
methodOptions: MethodOptions,
methodTrace: MethodTrace,
methodPatch: MethodPatch,
methodQuery: MethodQuery,
}

// httpReadResponse - Used for test mocking http.ReadResponse
Expand Down Expand Up @@ -1067,6 +1069,12 @@ func (app *App) Patch(path string, handler any, handlers ...any) Router {
return app.Add([]string{MethodPatch}, path, handler, handlers...)
}

// Query registers a route for QUERY methods that performs a safe, idempotent
// query with a request body.
func (app *App) Query(path string, handler any, handlers ...any) Router {
return app.Add([]string{MethodQuery}, path, handler, handlers...)
}

// Add allows you to specify multiple HTTP methods to register a route.
// The provided handlers are executed in order, starting with `handler` and then the variadic `handlers`.
func (app *App) Add(methods []string, path string, handler any, handlers ...any) Router {
Expand Down
3 changes: 3 additions & 0 deletions app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1298,6 +1298,9 @@ func Test_App_Methods(t *testing.T) {
app.Trace("/:john?/:doe?", dummyHandler)
testStatus200(t, app, "/john/doe", MethodTrace)

app.Query("/:john?/:doe?", dummyHandler)
testStatus200(t, app, "/john/doe", MethodQuery)

app.Get("/:john?/:doe?", dummyHandler)
testStatus200(t, app, "/john/doe", MethodGet)

Expand Down
5 changes: 5 additions & 0 deletions client/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,11 @@ func (r *Request) Patch(url string) (*Response, error) {
return r.SetURL(url).SetMethod(fiber.MethodPatch).Send()
}

// Query sends a QUERY request to the given URL.
func (r *Request) Query(url string) (*Response, error) {
return r.SetURL(url).SetMethod(fiber.MethodQuery).Send()
}

// Custom sends a request with a custom HTTP method to the given URL.
func (r *Request) Custom(url, method string) (*Response, error) {
return r.SetURL(url).SetMethod(method).Send()
Expand Down
1 change: 1 addition & 0 deletions constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const (
MethodConnect = "CONNECT" // RFC 7231, 4.3.6
MethodOptions = "OPTIONS" // RFC 7231, 4.3.7
MethodTrace = "TRACE" // RFC 7231, 4.3.8
MethodQuery = "QUERY" // RFC 10008
methodUse = "USE"
)

Expand Down
1 change: 1 addition & 0 deletions docs/api/constants.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const (
MethodConnect = "CONNECT" // RFC 7231, 4.3.6
MethodOptions = "OPTIONS" // RFC 7231, 4.3.7
MethodTrace = "TRACE" // RFC 7231, 4.3.8
MethodQuery = "QUERY" // RFC 10008
methodUse = "USE"
)
```
Expand Down
8 changes: 8 additions & 0 deletions docs/client/request.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,14 @@ func (r *Request) Head(url string) (*Response, error)
func (r *Request) Options(url string) (*Response, error)
```

### Query

**Query** sends a QUERY request. It sets the URL and method to QUERY, then sends the request.

```go title="Signature"
func (r *Request) Query(url string) (*Response, error)
```

### Custom

**Custom** sends a request using a custom HTTP method. For example, you can use this to send a TRACE or CONNECT request.
Expand Down
1 change: 1 addition & 0 deletions docs/partials/routing/handler.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ func (app *App) Connect(path string, handler any, handlers ...any) Router
func (app *App) Options(path string, handler any, handlers ...any) Router
func (app *App) Trace(path string, handler any, handlers ...any) Router
func (app *App) Patch(path string, handler any, handlers ...any) Router
func (app *App) Query(path string, handler any, handlers ...any) Router

// Add registers the same handlers on multiple methods at once.
// The handlers run in order, starting with `handler` and then the variadic `handlers`.
Expand Down
10 changes: 10 additions & 0 deletions domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,12 @@ func (d *domainRouter) Patch(path string, handler any, handlers ...any) Router {
return d.Add([]string{MethodPatch}, path, handler, handlers...)
}

// Query registers a route for QUERY methods.
// The handler only executes when the request hostname matches the domain pattern.
func (d *domainRouter) Query(path string, handler any, handlers ...any) Router {
return d.Add([]string{MethodQuery}, path, handler, handlers...)
}

// Add allows you to specify multiple HTTP methods to register a route.
// The handler only executes when the request hostname matches the domain pattern.
func (d *domainRouter) Add(methods []string, path string, handler any, handlers ...any) Router {
Expand Down Expand Up @@ -674,6 +680,10 @@ func (r *domainRegistering) Patch(handler any, handlers ...any) Register {
return r.Add([]string{MethodPatch}, handler, handlers...)
}

func (r *domainRegistering) Query(handler any, handlers ...any) Register {
return r.Add([]string{MethodQuery}, handler, handlers...)
}

func (r *domainRegistering) Add(methods []string, handler any, handlers ...any) Register {
converted := collectHandlers("domain", append([]any{handler}, handlers...)...)
wrapped := r.domain.wrapHandlers(converted)
Expand Down
6 changes: 6 additions & 0 deletions group.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,12 @@ func (grp *Group) Patch(path string, handler any, handlers ...any) Router {
return grp.Add([]string{MethodPatch}, path, handler, handlers...)
}

// Query registers a route for QUERY methods that performs a safe, idempotent
// query with a request body.
func (grp *Group) Query(path string, handler any, handlers ...any) Router {
return grp.Add([]string{MethodQuery}, path, handler, handlers...)
}

// Add allows you to specify multiple HTTP methods to register a route.
// The provided handlers are executed in order, starting with `handler` and then the variadic `handlers`.
func (grp *Group) Add(methods []string, path string, handler any, handlers ...any) Router {
Expand Down
5 changes: 4 additions & 1 deletion helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -935,6 +935,8 @@ func (app *App) methodInt(s string) int {
return methodTrace
case MethodPatch:
return methodPatch
case MethodQuery:
return methodQuery
default:
return -1
}
Expand All @@ -954,7 +956,8 @@ func IsMethodSafe(m string) bool {
case MethodGet,
MethodHead,
MethodOptions,
MethodTrace:
MethodTrace,
MethodQuery:
return true
default:
return false
Expand Down
3 changes: 2 additions & 1 deletion middleware/cors/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ type Config struct {
// AllowMethods defines a list methods allowed when accessing the resource.
// This is used in response to a preflight request.
//
// Optional. Default value []string{"GET", "POST", "HEAD", "PUT", "DELETE", "PATCH"}
// Optional. Default value []string{"GET", "POST", "HEAD", "PUT", "DELETE", "PATCH", "QUERY"}
AllowMethods []string

// AllowHeaders defines a list of request headers that can be used when
Expand Down Expand Up @@ -98,6 +98,7 @@ var ConfigDefault = Config{
fiber.MethodPut,
fiber.MethodDelete,
fiber.MethodPatch,
fiber.MethodQuery,
},
AllowHeaders: []string{},
AllowCredentials: false,
Expand Down
6 changes: 3 additions & 3 deletions middleware/cors/cors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ func testDefaultOrEmptyConfig(t *testing.T, app *fiber.App) {
ctx.Request.Header.Set(fiber.HeaderOrigin, "http://localhost")
h(ctx)

require.Equal(t, "GET, POST, HEAD, PUT, DELETE, PATCH", string(ctx.Response.Header.Peek(fiber.HeaderAccessControlAllowMethods)))
require.Equal(t, "GET, POST, HEAD, PUT, DELETE, PATCH, QUERY", string(ctx.Response.Header.Peek(fiber.HeaderAccessControlAllowMethods)))
require.Empty(t, string(ctx.Response.Header.Peek(fiber.HeaderAccessControlAllowHeaders)))
require.Empty(t, string(ctx.Response.Header.Peek(fiber.HeaderAccessControlMaxAge)))
}
Expand Down Expand Up @@ -642,7 +642,7 @@ func Test_CORS_Headers_BasedOnRequestType(t *testing.T) {
handler(ctx)
require.Equal(t, 204, ctx.Response.StatusCode(), "Status code should be 204")
require.Equal(t, "*", string(ctx.Response.Header.Peek(fiber.HeaderAccessControlAllowOrigin)), "Access-Control-Allow-Origin header should be set")
require.Equal(t, "GET, POST, HEAD, PUT, DELETE, PATCH", string(ctx.Response.Header.Peek(fiber.HeaderAccessControlAllowMethods)), "Access-Control-Allow-Methods header should be set (preflight request)")
require.Equal(t, "GET, POST, HEAD, PUT, DELETE, PATCH, QUERY", string(ctx.Response.Header.Peek(fiber.HeaderAccessControlAllowMethods)), "Access-Control-Allow-Methods header should be set (preflight request)")
require.Empty(t, string(ctx.Response.Header.Peek(fiber.HeaderAccessControlAllowHeaders)), "Access-Control-Allow-Headers header should be set (preflight request)")
}
})
Expand Down Expand Up @@ -676,7 +676,7 @@ func Test_CORS_Headers_BasedOnRequestType(t *testing.T) {
handler(ctx)
require.Equal(t, 204, ctx.Response.StatusCode(), "Status code should be 204")
require.Equal(t, "*", string(ctx.Response.Header.Peek(fiber.HeaderAccessControlAllowOrigin)), "Access-Control-Allow-Origin header should be set")
require.Equal(t, "GET, POST, HEAD, PUT, DELETE, PATCH", string(ctx.Response.Header.Peek(fiber.HeaderAccessControlAllowMethods)), "Access-Control-Allow-Methods header should be set (preflight request)")
require.Equal(t, "GET, POST, HEAD, PUT, DELETE, PATCH, QUERY", string(ctx.Response.Header.Peek(fiber.HeaderAccessControlAllowMethods)), "Access-Control-Allow-Methods header should be set (preflight request)")
Comment thread
gaby marked this conversation as resolved.
require.Equal(t, "X-Custom-Header", string(ctx.Response.Header.Peek(fiber.HeaderAccessControlAllowHeaders)), "Access-Control-Allow-Headers header should be set (preflight request)")
}
})
Expand Down
2 changes: 1 addition & 1 deletion middleware/csrf/csrf.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func New(config ...Config) fiber.Handler {

// Action depends on the HTTP method
switch c.Method() {
case fiber.MethodGet, fiber.MethodHead, fiber.MethodOptions, fiber.MethodTrace:
case fiber.MethodGet, fiber.MethodHead, fiber.MethodOptions, fiber.MethodTrace, fiber.MethodQuery:
cookieToken := c.Cookies(cfg.CookieName)

if cookieToken != "" {
Expand Down
2 changes: 1 addition & 1 deletion middleware/logger/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ func methodColor(method string, colors *fiber.Colors) string {
return ""
}
switch method {
case fiber.MethodGet:
case fiber.MethodGet, fiber.MethodQuery:
return colors.Cyan
case fiber.MethodPost:
return colors.Green
Expand Down
7 changes: 7 additions & 0 deletions register.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type Register interface {
Options(handler any, handlers ...any) Register
Trace(handler any, handlers ...any) Register
Patch(handler any, handlers ...any) Register
Query(handler any, handlers ...any) Register

Add(methods []string, handler any, handlers ...any) Register

Expand Down Expand Up @@ -106,6 +107,12 @@ func (r *Registering) Patch(handler any, handlers ...any) Register {
return r.Add([]string{MethodPatch}, handler, handlers...)
}

// Query registers a route for QUERY methods that performs a safe, idempotent
// query with a request body.
func (r *Registering) Query(handler any, handlers ...any) Register {
return r.Add([]string{MethodQuery}, handler, handlers...)
}

// Add allows you to specify multiple HTTP methods to register a route.
// The provided handlers are executed in order, starting with `handler` and then the variadic `handlers`.
func (r *Registering) Add(methods []string, handler any, handlers ...any) Register {
Expand Down
1 change: 1 addition & 0 deletions router.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type Router interface {
Options(path string, handler any, handlers ...any) Router
Trace(path string, handler any, handlers ...any) Router
Patch(path string, handler any, handlers ...any) Router
Query(path string, handler any, handlers ...any) Router

Add(methods []string, path string, handler any, handlers ...any) Router
All(path string, handler any, handlers ...any) Router
Expand Down