Former-commit-id: 55589069c8ed458183d28f32870fdf8f233629c6
This commit is contained in:
Gerasimos (Makis) Maropoulos 2020-07-11 16:14:31 +03:00
parent 3574816e1d
commit c8ed26ee51
8 changed files with 981 additions and 923 deletions

View File

@ -438,6 +438,7 @@ New Package-level Variables:
New Context Methods: New Context Methods:
- `Context.SetErr(error)` and `Context.GetErr() error` helpers
- `Context.Compress(bool) error` and `Context.CompressReader(bool) error` - `Context.Compress(bool) error` and `Context.CompressReader(bool) error`
- `Context.Clone() Context` returns a copy of the Context. - `Context.Clone() Context` returns a copy of the Context.
- `Context.IsCanceled() bool` reports whether the request has been canceled by the client. - `Context.IsCanceled() bool` reports whether the request has been canceled by the client.

2
cli.go
View File

@ -2,7 +2,7 @@ package iris
// +------------------------------------------------------------+ // +------------------------------------------------------------+
// | Bridge code between iris-cli and iris web application | // | Bridge code between iris-cli and iris web application |
// | https://github.com/kataras/iris-cli | // | https://github.com/kataras/iris-cli |
// +------------------------------------------------------------+ // +------------------------------------------------------------+
import ( import (

View File

@ -10,7 +10,7 @@ import (
"github.com/andybalholm/brotli" "github.com/andybalholm/brotli"
"github.com/klauspost/compress/flate" "github.com/klauspost/compress/flate"
"github.com/klauspost/compress/gzip" "github.com/klauspost/compress/gzip"
"github.com/klauspost/compress/s2" "github.com/klauspost/compress/s2" // snappy output but likely faster decompression.
"github.com/klauspost/compress/snappy" "github.com/klauspost/compress/snappy"
) )
@ -184,11 +184,10 @@ func AcquireCompressResponseWriter(w ResponseWriter, r *http.Request, level int)
return nil, ErrResponseNotCompressed return nil, ErrResponseNotCompressed
} }
encoding := negotiateAcceptHeader(acceptEncoding, []string{"gzip", "deflate", "br", "snappy", "s2"}, "") encoding := negotiateAcceptHeader(acceptEncoding, []string{GZIP, DEFLATE, BROTLI, SNAPPY, S2}, IDENTITY)
if encoding == "" { if encoding == "" {
return nil, fmt.Errorf("%w: %s", ErrNotSupportedCompression, encoding) return nil, fmt.Errorf("%w: %s", ErrNotSupportedCompression, encoding)
} }
AddCompressHeaders(w.Header(), encoding)
v := compressWritersPool.Get().(*CompressResponseWriter) v := compressWritersPool.Get().(*CompressResponseWriter)
v.ResponseWriter = w v.ResponseWriter = w
@ -212,6 +211,8 @@ func AcquireCompressResponseWriter(w ResponseWriter, r *http.Request, level int)
} }
v.CompressWriter = encWriter v.CompressWriter = encWriter
AddCompressHeaders(w.Header(), encoding)
return v, nil return v, nil
} }

View File

@ -4505,6 +4505,32 @@ func (ctx *Context) Application() Application {
return ctx.app return ctx.app
} }
const errorContextKey = "iris.context.error"
// SetErr is just a helper that sets an error value
// as a context value, it does nothing more.
// Also, by-default this error's value is written to the client
// on failures when no registered error handler is available (see `Party.On(Any)ErrorCode`).
// See `GetError` to retrieve it back.
//
// Note that, if you want to stop the chain
// with an error see the `StopWithError` instead.
func (ctx *Context) SetErr(err error) {
ctx.Values().Set(errorContextKey, err)
}
// GetErr is a helper which retrieves
// the error value stored by `SetErr`.
func (ctx *Context) GetErr() error {
if v := ctx.Values().Get(errorContextKey); v != nil {
if err, ok := v.(error); ok {
return err
}
}
return nil
}
const idContextKey = "iris.context.id" const idContextKey = "iris.context.id"
// SetID sets an ID, any value, to the Request Context. // SetID sets an ID, any value, to the Request Context.

View File

@ -548,8 +548,14 @@ func (h *routerHandler) FireErrorCode(ctx *context.Context) {
break break
} }
// not error handler found, write a default message. // not error handler found,
ctx.WriteString(context.StatusText(statusCode)) // see if failed with a stored error, and if so
// then render it, otherwise write a default message.
if err := ctx.GetErr(); err != nil {
ctx.WriteString(err.Error())
} else {
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 {

View File

@ -114,14 +114,23 @@ type compatibleErr interface {
Error() string Error() string
} }
// dispatchErr writes the error to the response. // dispatchErr sets the error status code
// and the error value to the context.
// The APIBuilder's On(Any)ErrorCode is responsible to render this error code.
func dispatchErr(ctx *context.Context, status int, err error) bool { func dispatchErr(ctx *context.Context, status int, err error) bool {
if err == nil { if err == nil {
return false return false
} }
ctx.StatusCode(status) if err != ErrStopExecution {
DefaultErrorHandler.HandleError(ctx, err) if status == 0 || !context.StatusCodeNotSuccessful(status) {
status = DefaultErrStatusCode
}
ctx.StatusCode(status)
}
ctx.SetErr(err)
return true return true
} }

View File

@ -258,3 +258,24 @@ func TestPreflightResult(t *testing.T) {
e.POST("/alternative").WithJSON(testInput{expected4.Name}). e.POST("/alternative").WithJSON(testInput{expected4.Name}).
Expect().Status(httptest.StatusAccepted).JSON().Equal(expected4) Expect().Status(httptest.StatusAccepted).JSON().Equal(expected4)
} }
func TestResponseErr(t *testing.T) {
app := iris.New()
var expectedErr = errors.New("response error")
app.OnAnyErrorCode(func(ctx iris.Context) {
err := ctx.GetErr()
if err != expectedErr {
t.Fatalf("expected error value does not match")
}
ctx.WriteString(err.Error())
})
app.ConfigureContainer().Get("/", func() Response {
return Response{Code: iris.StatusBadGateway, Err: expectedErr}
})
e := httptest.New(t, app)
e.GET("/").Expect().Status(iris.StatusBadGateway).Body().Equal("response error")
}