1
0
mirror of https://github.com/kataras/iris.git synced 2026-01-08 12:31:58 +00:00

(#1554) Add support for all common compressions (write and read)

- Remove the context.Context interface and export the *context, the iris.Context now points to the pointer\nSupport compression and rate limiting in the FileServer\nBit of code organisation


Former-commit-id: ad1c61bf968059510c6be9e7f2cceec7da70ba17
This commit is contained in:
Gerasimos (Makis) Maropoulos
2020-07-10 23:21:09 +03:00
parent 645da2b2ef
commit 0f113dfcda
112 changed files with 2119 additions and 3390 deletions

View File

@@ -116,7 +116,7 @@ func (repo *repository) register(route *Route, rule RouteRegisterRule) (*Route,
return route, nil
}
var defaultOverlapFilter = func(ctx context.Context) bool {
var defaultOverlapFilter = func(ctx *context.Context) bool {
if ctx.IsStopped() {
// It's stopped and the response can be overridden by a new handler.
rs, ok := ctx.ResponseWriter().(context.ResponseWriterReseter)
@@ -131,7 +131,7 @@ func overlapRoute(r *Route, next *Route) {
next.BuildHandlers()
nextHandlers := next.Handlers[0:]
decisionHandler := func(ctx context.Context) {
decisionHandler := func(ctx *context.Context) {
ctx.Next()
if !defaultOverlapFilter(ctx) {
@@ -925,7 +925,7 @@ func (api *APIBuilder) registerResourceRoute(reqPath string, h context.Handler)
// Returns the GET *Route.
func (api *APIBuilder) StaticContent(reqPath string, cType string, content []byte) *Route {
modtime := time.Now()
h := func(ctx context.Context) {
h := func(ctx *context.Context) {
ctx.ContentType(cType)
if _, err := ctx.WriteWithExpiration(content, modtime); err != nil {
ctx.StatusCode(http.StatusInternalServerError)
@@ -975,7 +975,7 @@ func (api *APIBuilder) Favicon(favPath string, requestPath ...string) *Route {
modtime := time.Now()
cType := TypeByFilename(favPath)
h := func(ctx context.Context) {
h := func(ctx *context.Context) {
ctx.ContentType(cType)
if _, err := ctx.WriteWithExpiration(cacheFav, modtime); err != nil {
ctx.StatusCode(http.StatusInternalServerError)
@@ -1030,7 +1030,7 @@ func (api *APIBuilder) OnAnyErrorCode(handlers ...context.Handler) (routes []*Ro
//
// Examples: https://github.com/kataras/iris/tree/master/_examples/view
func (api *APIBuilder) Layout(tmplLayoutFile string) Party {
api.Use(func(ctx context.Context) {
api.Use(func(ctx *context.Context) {
ctx.ViewLayout(tmplLayoutFile)
ctx.Next()
})

View File

@@ -73,7 +73,7 @@ func genPaths(routesLength, minCharLength, maxCharLength int) []string {
func BenchmarkAPIBuilder(b *testing.B) {
rand.Seed(time.Now().Unix())
noOpHandler := func(ctx context.Context) {}
noOpHandler := func(ctx *context.Context) {}
handlersPerRoute := make(context.Handlers, 12)
for i := 0; i < cap(handlersPerRoute); i++ {
handlersPerRoute[i] = noOpHandler

View File

@@ -42,9 +42,9 @@ func (api *APIContainer) PartyFunc(relativePath string, fn func(*APIContainer))
// Container.GetErrorHandler = func(ctx iris.Context) hero.ErrorHandler { return errorHandler }
//
// See `RegisterDependency`, `Use`, `Done` and `Handle` too.
func (api *APIContainer) OnError(errorHandler func(context.Context, error)) {
func (api *APIContainer) OnError(errorHandler func(*context.Context, error)) {
errHandler := hero.ErrorHandlerFunc(errorHandler)
api.Container.GetErrorHandler = func(ctx context.Context) hero.ErrorHandler {
api.Container.GetErrorHandler = func(ctx *context.Context) hero.ErrorHandler {
return errHandler
}
}

View File

@@ -6,7 +6,6 @@ import (
"html"
"html/template"
"io"
"io/ioutil"
"net/http"
"net/url"
"os"
@@ -22,7 +21,7 @@ import (
const indexName = "/index.html"
// DirListFunc is the function signature for customizing directory and file listing.
type DirListFunc func(ctx context.Context, dirName string, dir http.File) error
type DirListFunc func(ctx *context.Context, dirOptions DirOptions, dirName string, dir http.File) error
// Attachments options for files to be downloaded and saved locally by the client.
// See `DirOptions`.
@@ -46,7 +45,7 @@ type DirOptions struct {
// if end developer does not managed to handle it by hand.
IndexName string
// When files should served under compression.
Gzip bool
Compress bool
// List the files inside the current requested directory if `IndexName` not found.
ShowList bool
@@ -56,8 +55,6 @@ type DirOptions struct {
DirList DirListFunc
// Files downloaded and saved locally.
// Gzip option MUST be false in order for this to work.
// TODO(@kataras): find a way to make it work.
Attachments Attachments
// When embedded.
@@ -66,7 +63,7 @@ type DirOptions struct {
AssetNames func() []string // called once.
// Optional validator that loops through each requested resource.
AssetValidator func(ctx context.Context, name string) bool
AssetValidator func(ctx *context.Context, name string) bool
}
func getDirOptions(opts ...DirOptions) (options DirOptions) {
@@ -80,6 +77,12 @@ func getDirOptions(opts ...DirOptions) (options DirOptions) {
options.IndexName = prefix(options.IndexName, "/")
}
if !options.Attachments.Enable {
// make sure rate limiting is not used when attachments are not.
options.Attachments.Limit = 0
options.Attachments.Burst = 0
}
return
}
@@ -300,17 +303,16 @@ func FileServer(directory string, opts ...DirOptions) context.Handler {
// panic("FileServer: system directory: " + directory + " does not exist")
// }
plainStatusCode := func(ctx context.Context, statusCode int) {
if writer, ok := ctx.ResponseWriter().(*context.GzipResponseWriter); ok && writer != nil {
writer.ResetBody()
writer.Disable()
plainStatusCode := func(ctx *context.Context, statusCode int) {
if writer, ok := ctx.ResponseWriter().(*context.CompressResponseWriter); ok {
writer.Disabled = true
}
ctx.StatusCode(statusCode)
}
dirList := options.DirList
if dirList == nil {
dirList = func(ctx context.Context, dirName string, dir http.File) error {
dirList = func(ctx *context.Context, dirOptions DirOptions, dirName string, dir http.File) error {
dirs, err := dir.Readdir(-1)
if err != nil {
return err
@@ -323,6 +325,7 @@ func FileServer(directory string, opts ...DirOptions) context.Handler {
if err != nil {
return err
}
for _, d := range dirs {
name := d.Name()
if d.IsDir() {
@@ -341,10 +344,14 @@ func FileServer(directory string, opts ...DirOptions) context.Handler {
Path: upath,
} // edit here to redirect correctly, standard library misses that.
downloadAttr := ""
if dirOptions.Attachments.Enable && !d.IsDir() {
downloadAttr = " download" // fixes chrome Resource interpreted, other browsers will just ignore this <a> attribute.
}
// name may contain '?' or '#', which must be escaped to remain
// part of the URL path, and not indicate the start of a query
// string or fragment.
_, err = ctx.Writef("<a href=\"%s\">%s</a>\n", url.String(), html.EscapeString(name))
_, err = ctx.Writef("<a href=\"%s\"%s>%s</a>\n", url.String(), downloadAttr, html.EscapeString(name))
if err != nil {
return err
}
@@ -354,17 +361,10 @@ func FileServer(directory string, opts ...DirOptions) context.Handler {
}
}
h := func(ctx context.Context) {
h := func(ctx *context.Context) {
name := prefix(ctx.Request().URL.Path, "/")
ctx.Request().URL.Path = name
gzip := options.Gzip
if !gzip {
// if false then check if the dev did something like `ctx.Gzip(true)`.
_, gzip = ctx.ResponseWriter().(*context.GzipResponseWriter)
}
// ctx.Gzip(options.Gzip)
f, err := fs.Open(name)
if err != nil {
plainStatusCode(ctx, http.StatusNotFound)
@@ -378,6 +378,7 @@ func FileServer(directory string, opts ...DirOptions) context.Handler {
return
}
indexFound := false
// use contents of index.html for directory, if present
if info.IsDir() && options.IndexName != "" {
// Note that, in contrast of the default net/http mechanism;
@@ -397,6 +398,7 @@ func FileServer(directory string, opts ...DirOptions) context.Handler {
if err == nil {
info = infoIndex
f = fIndex
indexFound = true
}
}
}
@@ -414,7 +416,7 @@ func FileServer(directory string, opts ...DirOptions) context.Handler {
return
}
ctx.SetLastModified(info.ModTime())
err = dirList(ctx, info.Name(), f)
err = dirList(ctx, options, info.Name(), f)
if err != nil {
ctx.Application().Logger().Errorf("FileServer: dirList: %v", err)
plainStatusCode(ctx, http.StatusInternalServerError)
@@ -451,32 +453,10 @@ func FileServer(directory string, opts ...DirOptions) context.Handler {
// and the binary data inside "f".
detectOrWriteContentType(ctx, info.Name(), f)
if gzip {
// set the last modified as "serveContent" does.
ctx.SetLastModified(info.ModTime())
// write the file to the response writer.
contents, err := ioutil.ReadAll(f)
if err != nil {
ctx.Application().Logger().Debugf("err reading file: %v", err)
plainStatusCode(ctx, http.StatusInternalServerError)
return
}
// Use `WriteNow` instead of `Write`
// because we need to know the compressed written size before
// the `FlushResponse`.
_, err = ctx.GzipResponseWriter().Write(contents)
if err != nil {
ctx.Application().Logger().Debugf("short write: %v", err)
plainStatusCode(ctx, http.StatusInternalServerError)
return
}
return
}
if options.Attachments.Enable {
// if not index file and attachments should be force-sent:
if !indexFound && options.Attachments.Enable {
destName := info.Name()
// diposition := "attachment"
if nameFunc := options.Attachments.NameFunc; nameFunc != nil {
destName = nameFunc(destName)
}
@@ -484,6 +464,14 @@ func FileServer(directory string, opts ...DirOptions) context.Handler {
ctx.ResponseWriter().Header().Set(context.ContentDispositionHeaderKey, "attachment;filename="+destName)
}
ctx.Compress(options.Compress)
// if gzip {
// ctx.Compress(true)
// context.AddCompressHeaders(ctx.ResponseWriter().Header())
// // to not write the content-length( see http.serveContent):
// // ctx.ResponseWriter().Header().Set(context.ContentEncodingHeaderKey, context.GzipHeaderValue)
// }
// If limit is 0 then same as ServeContent.
ctx.ServeContentWithRate(f, info.Name(), info.ModTime(), options.Attachments.Limit, options.Attachments.Burst)
if serveCode := ctx.GetStatusCode(); context.StatusCodeNotSuccessful(serveCode) {
@@ -520,7 +508,7 @@ func StripPrefix(prefix string, h context.Handler) context.Handler {
}
canonicalPrefix = toWebPath(canonicalPrefix)
return func(ctx context.Context) {
return func(ctx *context.Context) {
if p := strings.TrimPrefix(ctx.Request().URL.Path, canonicalPrefix); len(p) < len(ctx.Request().URL.Path) {
ctx.Request().URL.Path = p
h(ctx)
@@ -551,7 +539,7 @@ func Abs(path string) string {
// The algorithm uses at most sniffLen bytes to make its decision.
const sniffLen = 512
func detectOrWriteContentType(ctx context.Context, name string, content io.ReadSeeker) (string, error) {
func detectOrWriteContentType(ctx *context.Context, name string, content io.ReadSeeker) (string, error) {
// If Content-Type isn't set, use the file's extension to find it, but
// if the Content-Type is unset explicitly, do not sniff the type.
ctypes, haveType := ctx.ResponseWriter().Header()["Content-Type"]
@@ -580,7 +568,7 @@ func detectOrWriteContentType(ctx context.Context, name string, content io.ReadS
// localRedirect gives a Moved Permanently response.
// It does not convert relative paths to absolute paths like Redirect does.
func localRedirect(ctx context.Context, newPath string) {
func localRedirect(ctx *context.Context, newPath string) {
if q := ctx.Request().URL.RawQuery; q != "" {
newPath += "?" + q
}
@@ -619,7 +607,7 @@ func DirListRich(opts ...DirListRichOptions) DirListFunc {
options.Tmpl = DirListRichTemplate
}
return func(ctx context.Context, dirName string, dir http.File) error {
return func(ctx *context.Context, dirOptions DirOptions, dirName string, dir http.File) error {
dirs, err := dir.Readdir(-1)
if err != nil {
return err
@@ -655,12 +643,14 @@ func DirListRich(opts ...DirListRichOptions) DirListFunc {
url := url.URL{Path: upath}
shouldDownload := dirOptions.Attachments.Enable && !d.IsDir()
pageData.Files = append(pageData.Files, fileInfoData{
Info: d,
ModTime: d.ModTime().UTC().Format(http.TimeFormat),
Path: url.String(),
RelPath: path.Join(ctx.Path(), name),
Name: html.EscapeString(name),
Info: d,
ModTime: d.ModTime().UTC().Format(http.TimeFormat),
Path: url.String(),
RelPath: path.Join(ctx.Path(), name),
Name: html.EscapeString(name),
Download: shouldDownload,
})
}
@@ -679,11 +669,12 @@ type (
}
fileInfoData struct {
Info os.FileInfo
ModTime string // format-ed time.
Path string // the request path.
RelPath string // file path without the system directory itself (we are not exposing it to the user).
Name string // the html-escaped name.
Info os.FileInfo
ModTime string // format-ed time.
Path string // the request path.
RelPath string // file path without the system directory itself (we are not exposing it to the user).
Name string // the html-escaped name.
Download bool // the file should be downloaded (attachment instead of inline view).
}
)
@@ -786,7 +777,11 @@ var DirListRichTemplate = template.Must(template.New("dirlist").
{{ range $idx, $file := .Files }}
<tr>
<td>{{ $idx }}</td>
<td><a href="{{ $file.Path }}" title="{{ $file.ModTime }}">{{ $file.Name }}</a></td>
{{ if $file.Download }}
<td><a href="{{ $file.Path }}" title="{{ $file.ModTime }}" download>{{ $file.Name }}</a></td>
{{ else }}
<td><a href="{{ $file.Path }}" title="{{ $file.ModTime }}">{{ $file.Name }}</a></td>
{{ end }}
{{ if $file.Info.IsDir }}
<td>Dir</td>
{{ else }}

View File

@@ -25,11 +25,11 @@ type (
HTTPErrorHandler
// HandleRequest should handle the request based on the Context.
HandleRequest(ctx context.Context)
HandleRequest(ctx *context.Context)
// Build should builds the handler, it's being called on router's BuildRouter.
Build(provider RoutesProvider) error
// RouteExists reports whether a particular route exists.
RouteExists(ctx context.Context, method, path string) bool
RouteExists(ctx *context.Context, method, path string) bool
}
// HTTPErrorHandler should contain a method `FireErrorCode` which
@@ -37,7 +37,7 @@ type (
HTTPErrorHandler interface {
// FireErrorCode should send an error response to the client based
// on the given context's response status code.
FireErrorCode(ctx context.Context)
FireErrorCode(ctx *context.Context)
}
)
@@ -294,7 +294,7 @@ func bindMultiParamTypesHandler(r *Route) {
currentStatusCode = http.StatusOK
}
decisionHandler := func(ctx context.Context) {
decisionHandler := func(ctx *context.Context) {
// println("core/router/handler.go: decision handler; " + ctx.Path() + " route.Name: " + r.Name + " vs context's " + ctx.GetCurrentRoute().Name())
currentRoute := ctx.GetCurrentRoute()
@@ -318,7 +318,7 @@ func bindMultiParamTypesHandler(r *Route) {
r.topLink.beginHandlers = append(context.Handlers{decisionHandler}, r.topLink.beginHandlers...)
}
func (h *routerHandler) canHandleSubdomain(ctx context.Context, subdomain string) bool {
func (h *routerHandler) canHandleSubdomain(ctx *context.Context, subdomain string) bool {
if subdomain == "" {
return true
}
@@ -356,7 +356,7 @@ func (h *routerHandler) canHandleSubdomain(ctx context.Context, subdomain string
return true
}
func (h *routerHandler) HandleRequest(ctx context.Context) {
func (h *routerHandler) HandleRequest(ctx *context.Context) {
method := ctx.Method()
path := ctx.Path()
config := h.config // ctx.Application().GetConfigurationReadOnly()
@@ -445,18 +445,18 @@ func statusCodeSuccessful(statusCode int) bool {
// FireErrorCode handles the response's error response.
// If `Configuration.ResetOnFireErrorCode()` is true
// and the response writer was a recorder or a gzip writer one
// and the response writer was a recorder one
// then it will try to reset the headers and the body before calling the
// registered (or default) error handler for that error code set by
// `ctx.StatusCode` method.
func (h *routerHandler) FireErrorCode(ctx context.Context) {
func (h *routerHandler) FireErrorCode(ctx *context.Context) {
// On common response writer, always check
// if we can't reset the body and the body has been filled
// which means that the status code already sent,
// then do not fire this custom error code,
// rel: context/context.go#EndRequest.
//
// Note that, this is set to 0 on recorder and gzip writer because they cache the response,
// Note that, this is set to 0 on recorder because it holds the response before sent,
// so we check their len(Body()) instead, look below.
if ctx.ResponseWriter().Written() > 0 {
return
@@ -473,21 +473,17 @@ func (h *routerHandler) FireErrorCode(ctx context.Context) {
// reset if previous content and it's recorder, keep the status code.
w.ClearHeaders()
w.ResetBody()
} else if w, ok := ctx.ResponseWriter().(*context.GzipResponseWriter); ok {
} else if w, ok := ctx.ResponseWriter().(*context.CompressResponseWriter); ok {
// reset and disable the gzip in order to be an expected form of http error result
w.ResetBody()
w.Disable()
w.Disabled = true
}
} else {
// check if a body already set (the error response is handled by the handler itself, see `Context.EndRequest`)
// check if a body already set (the error response is handled by the handler itself,
// see `Context.EndRequest`)
if w, ok := ctx.IsRecording(); ok {
if len(w.Body()) > 0 {
return
}
} else if w, ok := ctx.ResponseWriter().(*context.GzipResponseWriter); ok {
if len(w.Body()) > 0 {
return
}
}
}
@@ -526,7 +522,7 @@ func (h *routerHandler) FireErrorCode(ctx context.Context) {
// because may the user want to add a fallback error code
// i.e
// users := app.Party("/users")
// users.Done(func(ctx context.Context){ if ctx.StatusCode() == 400 { /* custom error code for /users */ }})
// users.Done(func(ctx *context.Context){ if ctx.StatusCode() == 400 { /* custom error code for /users */ }})
// use .HandlerIndex
// that sets the current handler index to zero
@@ -556,7 +552,7 @@ func (h *routerHandler) FireErrorCode(ctx context.Context) {
ctx.WriteString(context.StatusText(statusCode))
}
func (h *routerHandler) subdomainAndPathAndMethodExists(ctx context.Context, t *trie, method, path string) bool {
func (h *routerHandler) subdomainAndPathAndMethodExists(ctx *context.Context, t *trie, method, path string) bool {
if method != "" && method != t.method {
return false
}
@@ -599,7 +595,7 @@ func (h *routerHandler) subdomainAndPathAndMethodExists(ctx context.Context, t *
// RouteExists reports whether a particular route exists
// It will search from the current subdomain of context's host, if not inside the root domain.
func (h *routerHandler) RouteExists(ctx context.Context, method, path string) bool {
func (h *routerHandler) RouteExists(ctx *context.Context, method, path string) bool {
for i := range h.trees {
t := h.trees[i]
if h.subdomainAndPathAndMethodExists(ctx, t, method, path) {

View File

@@ -72,7 +72,7 @@ func (e ExecutionOptions) buildHandler(h context.Handler) context.Handler {
return h
}
return func(ctx context.Context) {
return func(ctx *context.Context) {
// Proceed will fire the handler and return false here if it doesn't contain a `ctx.Next()`,
// so we add the `ctx.Next()` wherever is necessary in order to eliminate any dev's misuse.
if !ctx.Proceed(h) {

View File

@@ -19,7 +19,7 @@ var (
)
func writeStringHandler(text string, withNext bool) context.Handler {
return func(ctx context.Context) {
return func(ctx *context.Context) {
ctx.WriteString(text)
if withNext {
ctx.Next()

View File

@@ -154,7 +154,10 @@ type Party interface {
//
// Alternatively, to get just the handler for that look the FileServer function instead.
//
// api.HandleDir("/static", "./assets", DirOptions {ShowList: true, Gzip: true, IndexName: "index.html"})
// api.HandleDir("/static", "./assets", DirOptions {
// ShowList: true,
// Compress: true,
// IndexName: "index.html"})
//
// Returns all the registered routes, including GET index and path patterm and HEAD.
//

View File

@@ -194,7 +194,7 @@ func (router *Router) WrapRouter(wrapperFunc WrapperFunc) {
}
// ServeHTTPC serves the raw context, useful if we have already a context, it by-pass the wrapper.
func (router *Router) ServeHTTPC(ctx context.Context) {
func (router *Router) ServeHTTPC(ctx *context.Context) {
router.requestHandler.HandleRequest(ctx)
}
@@ -204,6 +204,6 @@ func (router *Router) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// RouteExists reports whether a particular route exists
// It will search from the current subdomain of context's host, if not inside the root domain.
func (router *Router) RouteExists(ctx context.Context, method, path string) bool {
func (router *Router) RouteExists(ctx *context.Context, method, path string) bool {
return router.requestHandler.RouteExists(ctx, method, path)
}

View File

@@ -20,43 +20,43 @@ import (
// response should be the same at all cases.
var (
mainResponse = "main"
mainHandler = func(ctx context.Context) {
mainHandler = func(ctx *context.Context) {
ctx.WriteString(mainResponse)
ctx.Next()
}
firstUseResponse = "use1"
firstUseHandler = func(ctx context.Context) {
firstUseHandler = func(ctx *context.Context) {
ctx.WriteString(firstUseResponse)
ctx.Next()
}
secondUseResponse = "use2"
secondUseHandler = func(ctx context.Context) {
secondUseHandler = func(ctx *context.Context) {
ctx.WriteString(secondUseResponse)
ctx.Next()
}
firstUseGlobalResponse = "useglobal1"
firstUseGlobalHandler = func(ctx context.Context) {
firstUseGlobalHandler = func(ctx *context.Context) {
ctx.WriteString(firstUseGlobalResponse)
ctx.Next()
}
secondUseGlobalResponse = "useglobal2"
secondUseGlobalHandler = func(ctx context.Context) {
secondUseGlobalHandler = func(ctx *context.Context) {
ctx.WriteString(secondUseGlobalResponse)
ctx.Next()
}
firstDoneResponse = "done1"
firstDoneHandler = func(ctx context.Context) {
firstDoneHandler = func(ctx *context.Context) {
ctx.WriteString(firstDoneResponse)
ctx.Next()
}
secondDoneResponse = "done2"
secondDoneHandler = func(ctx context.Context) {
secondDoneHandler = func(ctx *context.Context) {
ctx.WriteString(secondDoneResponse)
}

View File

@@ -13,14 +13,14 @@ import (
func TestRouteExists(t *testing.T) {
// build the api
app := iris.New()
emptyHandler := func(context.Context) {}
emptyHandler := func(*context.Context) {}
// setup the tested routes
app.Handle("GET", "/route-exists", emptyHandler)
app.Handle("POST", "/route-with-param/{param}", emptyHandler)
// check RouteExists
app.Handle("GET", "/route-test", func(ctx context.Context) {
app.Handle("GET", "/route-test", func(ctx *context.Context) {
if ctx.RouteExists("GET", "/route-not-exists") {
t.Error("Route with path should not exists")
}

View File

@@ -36,18 +36,18 @@ type testRoute struct {
requests []testRouteRequest
}
var h = func(ctx context.Context) {
var h = func(ctx *context.Context) {
ctx.WriteString(ctx.Path())
}
var h2 = func(ctx context.Context) {
var h2 = func(ctx *context.Context) {
ctx.StatusCode(iris.StatusForbidden) // ! 200 but send the body as expected,
// we need that kind of behavior to determinate which handler is executed for routes that
// both having wildcard path but first one is registered on root level.
ctx.WriteString(ctx.Path())
}
func h3(ctx context.Context) {
func h3(ctx *context.Context) {
ctx.Writef(staticPathPrefixBody + ctx.Path())
}

View File

@@ -12,7 +12,7 @@ import (
"github.com/kataras/iris/v12/httptest"
)
var defaultErrHandler = func(ctx context.Context) {
var defaultErrHandler = func(ctx *context.Context) {
text := http.StatusText(ctx.GetStatusCode())
ctx.WriteString(text)
}
@@ -25,18 +25,18 @@ func TestOnAnyErrorCode(t *testing.T) {
expectedPrintBeforeExecuteErr := "printed before error"
// with a middleware
app.OnAnyErrorCode(func(ctx context.Context) {
app.OnAnyErrorCode(func(ctx *context.Context) {
buff.WriteString(expectedPrintBeforeExecuteErr)
ctx.Next()
}, defaultErrHandler)
expectedFoundResponse := "found"
app.Get("/found", func(ctx context.Context) {
app.Get("/found", func(ctx *context.Context) {
ctx.WriteString(expectedFoundResponse)
})
expected407 := "this should be sent, we manage the response response by ourselves"
app.Get("/407", func(ctx context.Context) {
app.Get("/407", func(ctx *context.Context) {
ctx.Record()
ctx.WriteString(expected407)
ctx.StatusCode(iris.StatusProxyAuthRequired)
@@ -64,12 +64,12 @@ func TestOnAnyErrorCode(t *testing.T) {
app2 := iris.New()
app2.Configure(iris.WithResetOnFireErrorCode)
app2.OnAnyErrorCode(func(ctx context.Context) {
app2.OnAnyErrorCode(func(ctx *context.Context) {
buff.WriteString(expectedPrintBeforeExecuteErr)
ctx.Next()
}, defaultErrHandler)
app2.Get("/406", func(ctx context.Context) {
app2.Get("/406", func(ctx *context.Context) {
ctx.Record()
ctx.WriteString("this should not be sent, only status text will be sent")
ctx.WriteString("the handler can handle 'rollback' of the text when error code fired because of the recorder")