mirror of
https://github.com/kataras/iris.git
synced 2025-02-02 15:30:36 +01:00
This commit is contained in:
parent
3582427df6
commit
ecb1c617df
|
@ -28,6 +28,7 @@ The codebase for Dependency Injection, Internationalization and localization and
|
||||||
|
|
||||||
## Fixes and Improvements
|
## Fixes and Improvements
|
||||||
|
|
||||||
|
- Add `iris.AllowQuerySemicolons` and `iris.WithoutServerError(iris.ErrURLQuerySemicolon)` to handle golang.org/issue/25192 as reported at: https://github.com/kataras/iris/issues/1875.
|
||||||
- Add new `Application.SetContextErrorHandler` to globally customize the default behavior (status code 500 without body) on `JSON`, `JSONP`, `Protobuf`, `MsgPack`, `XML`, `YAML` and `Markdown` method call write errors instead of catching the error on each handler.
|
- Add new `Application.SetContextErrorHandler` to globally customize the default behavior (status code 500 without body) on `JSON`, `JSONP`, `Protobuf`, `MsgPack`, `XML`, `YAML` and `Markdown` method call write errors instead of catching the error on each handler.
|
||||||
- Add new [x/pagination](x/pagination/pagination.go) sub-package which supports generics code (go 1.18+).
|
- Add new [x/pagination](x/pagination/pagination.go) sub-package which supports generics code (go 1.18+).
|
||||||
- Add new [middleware/modrevision](middleware/modrevision) middleware (example at [_examples/project/api/router.go]_examples/project/api/router.go).
|
- Add new [middleware/modrevision](middleware/modrevision) middleware (example at [_examples/project/api/router.go]_examples/project/api/router.go).
|
||||||
|
|
|
@ -32,7 +32,7 @@ func main() {
|
||||||
app.HandleMany(strings.Join(iris.WebDAVMethods, " "), "/{p:path}", iris.FromStd(webdavHandler))
|
app.HandleMany(strings.Join(iris.WebDAVMethods, " "), "/{p:path}", iris.FromStd(webdavHandler))
|
||||||
|
|
||||||
app.Listen(":8080",
|
app.Listen(":8080",
|
||||||
iris.WithoutServerError(iris.ErrServerClosed),
|
iris.WithoutServerError(iris.ErrServerClosed, iris.ErrURLQuerySemicolon),
|
||||||
iris.WithoutPathCorrection,
|
iris.WithoutPathCorrection,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ type MyType struct {
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := iris.New()
|
app := iris.New()
|
||||||
|
app.UseRouter(iris.AllowQuerySemicolons) // Optionally: to restore pre go1.17 behavior of url parsing.
|
||||||
|
|
||||||
app.Get("/", func(ctx iris.Context) {
|
app.Get("/", func(ctx iris.Context) {
|
||||||
var t MyType
|
var t MyType
|
||||||
|
@ -45,5 +46,6 @@ func main() {
|
||||||
// http://localhost:8080/simple?name=john&name=doe&name=kataras
|
// http://localhost:8080/simple?name=john&name=doe&name=kataras
|
||||||
//
|
//
|
||||||
// Note: this `WithEmptyFormError` will give an error if the query was empty.
|
// Note: this `WithEmptyFormError` will give an error if the query was empty.
|
||||||
app.Listen(":8080", iris.WithEmptyFormError)
|
app.Listen(":8080", iris.WithEmptyFormError,
|
||||||
|
iris.WithoutServerError(iris.ErrServerClosed, iris.ErrURLQuerySemicolon))
|
||||||
}
|
}
|
||||||
|
|
31
aliases.go
31
aliases.go
|
@ -2,8 +2,10 @@ package iris
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"path"
|
"path"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/kataras/iris/v12/cache"
|
"github.com/kataras/iris/v12/cache"
|
||||||
"github.com/kataras/iris/v12/context"
|
"github.com/kataras/iris/v12/context"
|
||||||
|
@ -328,6 +330,35 @@ var (
|
||||||
ctx.Next()
|
ctx.Next()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AllowQuerySemicolons returns a middleware that serves requests by converting any
|
||||||
|
// unescaped semicolons(;) in the URL query to ampersands(&).
|
||||||
|
//
|
||||||
|
// This restores the pre-Go 1.17 behavior of splitting query parameters on both
|
||||||
|
// semicolons and ampersands.
|
||||||
|
// (See golang.org/issue/25192 and https://github.com/kataras/iris/issues/1875).
|
||||||
|
// Note that this behavior doesn't match that of many proxies,
|
||||||
|
// and the mismatch can lead to security issues.
|
||||||
|
//
|
||||||
|
// AllowQuerySemicolons should be invoked before any Context read query or
|
||||||
|
// form methods are called.
|
||||||
|
//
|
||||||
|
// To skip HTTP Server logging for this type of warning:
|
||||||
|
// app.Listen/Run(..., iris.WithoutServerError(iris.ErrURLQuerySemicolon)).
|
||||||
|
AllowQuerySemicolons = func(ctx Context) {
|
||||||
|
// clopy of net/http.AllowQuerySemicolons.
|
||||||
|
r := ctx.Request()
|
||||||
|
if s := r.URL.RawQuery; strings.Contains(s, ";") {
|
||||||
|
r2 := new(http.Request)
|
||||||
|
*r2 = *r
|
||||||
|
r2.URL = new(url.URL)
|
||||||
|
*r2.URL = *r.URL
|
||||||
|
r2.URL.RawQuery = strings.ReplaceAll(s, ";", "&")
|
||||||
|
ctx.ResetRequest(r2)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Next()
|
||||||
|
}
|
||||||
|
|
||||||
// MatchImagesAssets is a simple regex expression
|
// MatchImagesAssets is a simple regex expression
|
||||||
// that can be passed to the DirOptions.Cache.CompressIgnore field
|
// that can be passed to the DirOptions.Cache.CompressIgnore field
|
||||||
// in order to skip compression on already-compressed file types
|
// in order to skip compression on already-compressed file types
|
||||||
|
|
62
iris.go
62
iris.go
|
@ -1,6 +1,7 @@
|
||||||
package iris
|
package iris
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
stdContext "context"
|
stdContext "context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -475,6 +476,40 @@ func (app *Application) ConfigureHost(configurators ...host.Configurator) *Appli
|
||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const serverLoggerPrefix = "[HTTP Server] "
|
||||||
|
|
||||||
|
type customHostServerLogger struct { // see #1875
|
||||||
|
parent io.Writer
|
||||||
|
ignoreLogs [][]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
var newLineBytes = []byte("\n")
|
||||||
|
|
||||||
|
func newCustomHostServerLogger(w io.Writer, ignoreLogs []string) *customHostServerLogger {
|
||||||
|
prefixAsByteSlice := []byte(serverLoggerPrefix)
|
||||||
|
|
||||||
|
// build the ignore lines.
|
||||||
|
ignoreLogsAsByteSlice := make([][]byte, 0, len(ignoreLogs))
|
||||||
|
for _, s := range ignoreLogs {
|
||||||
|
ignoreLogsAsByteSlice = append(ignoreLogsAsByteSlice, append(prefixAsByteSlice, []byte(s)...)) // append([]byte(s), newLineBytes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &customHostServerLogger{
|
||||||
|
parent: w,
|
||||||
|
ignoreLogs: ignoreLogsAsByteSlice,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *customHostServerLogger) Write(p []byte) (int, error) {
|
||||||
|
for _, ignoredLogBytes := range l.ignoreLogs {
|
||||||
|
if bytes.Equal(bytes.TrimSuffix(p, newLineBytes), ignoredLogBytes) {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return l.parent.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
// NewHost accepts a standard *http.Server object,
|
// NewHost accepts a standard *http.Server object,
|
||||||
// completes the necessary missing parts of that "srv"
|
// completes the necessary missing parts of that "srv"
|
||||||
// and returns a new, ready-to-use, host (supervisor).
|
// and returns a new, ready-to-use, host (supervisor).
|
||||||
|
@ -487,9 +522,10 @@ func (app *Application) NewHost(srv *http.Server) *host.Supervisor {
|
||||||
srv.Handler = app.Router
|
srv.Handler = app.Router
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if different ErrorLog provided, if not bind it with the framework's logger
|
// check if different ErrorLog provided, if not bind it with the framework's logger.
|
||||||
if srv.ErrorLog == nil {
|
if srv.ErrorLog == nil {
|
||||||
srv.ErrorLog = log.New(app.logger.Printer.Output, "[HTTP Server] ", 0)
|
serverLogger := newCustomHostServerLogger(app.logger.Printer.Output, app.config.IgnoreServerErrors)
|
||||||
|
srv.ErrorLog = log.New(serverLogger, serverLoggerPrefix, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if addr := srv.Addr; addr == "" {
|
if addr := srv.Addr; addr == "" {
|
||||||
|
@ -913,11 +949,23 @@ func Raw(f func() error) Runner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrServerClosed is returned by the Server's Serve, ServeTLS, ListenAndServe,
|
var (
|
||||||
// and ListenAndServeTLS methods after a call to Shutdown or Close.
|
// ErrServerClosed is logged by the standard net/http server when the server is terminated.
|
||||||
//
|
// Ignore it by passing this error to the `iris.WithoutServerError` configurator
|
||||||
// A shortcut for the `http#ErrServerClosed`.
|
// on `Application.Run/Listen` method.
|
||||||
var ErrServerClosed = http.ErrServerClosed
|
//
|
||||||
|
// An alias of the `http#ErrServerClosed`.
|
||||||
|
ErrServerClosed = http.ErrServerClosed
|
||||||
|
|
||||||
|
// ErrURLQuerySemicolon is logged by the standard net/http server when
|
||||||
|
// the request contains a semicolon (;) wihch, after go1.17 it's not used as a key-value separator character.
|
||||||
|
//
|
||||||
|
// Ignore it by passing this error to the `iris.WithoutServerError` configurator
|
||||||
|
// on `Application.Run/Listen` method.
|
||||||
|
//
|
||||||
|
// An alias of the `http#ErrServerClosed`.
|
||||||
|
ErrURLQuerySemicolon = errors.New("http: URL query contains semicolon, which is no longer a supported separator; parts of the query may be stripped when parsed; see golang.org/issue/25192")
|
||||||
|
)
|
||||||
|
|
||||||
// Listen builds the application and starts the server
|
// Listen builds the application and starts the server
|
||||||
// on the TCP network address "host:port" which
|
// on the TCP network address "host:port" which
|
||||||
|
|
Loading…
Reference in New Issue
Block a user