mirror of
https://github.com/kataras/iris.git
synced 2025-12-18 02:17:05 +00:00
🚌 next version preparation: new PreflightResult interface for hero handlers
Former-commit-id: ea2d7ab93889beaddfe269bd213d259d26df979f
This commit is contained in:
@@ -15,8 +15,24 @@ import (
|
||||
//
|
||||
// Example at: https://github.com/kataras/iris/tree/master/_examples/hero/overview.
|
||||
type Result interface {
|
||||
// Dispatch should sends the response to the context's response writer.
|
||||
Dispatch(ctx context.Context)
|
||||
// Dispatch should send a response to the client.
|
||||
Dispatch(context.Context)
|
||||
}
|
||||
|
||||
// PreflightResult is an interface which implementers
|
||||
// should be responsible to perform preflight checks of a <T> resource (or Result) before sent to the client.
|
||||
//
|
||||
// If a non-nil error returned from the `Preflight` method then the JSON result
|
||||
// will be not sent to the client and an ErrorHandler will be responsible to render the error.
|
||||
//
|
||||
// Usage: a custom struct value will be a JSON body response (by-default) but it contains
|
||||
// "Code int" and `ID string` fields, the "Code" should be the status code of the response
|
||||
// and the "ID" should be sent as a Header of "X-Request-ID: $ID".
|
||||
//
|
||||
// The caller can manage it at the handler itself. However,
|
||||
// to reduce thoese type of duplications it's preferable to use such a standard interface instead.
|
||||
type PreflightResult interface {
|
||||
Preflight(context.Context) error
|
||||
}
|
||||
|
||||
var defaultFailureResponse = Response{Code: DefaultErrStatusCode}
|
||||
@@ -294,6 +310,12 @@ func dispatchCommon(ctx context.Context,
|
||||
}
|
||||
|
||||
if v != nil {
|
||||
if p, ok := v.(PreflightResult); ok {
|
||||
if err := p.Preflight(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if d, ok := v.(Result); ok {
|
||||
// write the content type now (internal check for empty value)
|
||||
ctx.ContentType(contentType)
|
||||
|
||||
@@ -2,6 +2,8 @@ package hero_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/kataras/iris/v12"
|
||||
@@ -37,7 +39,7 @@ type testCustomResult struct {
|
||||
}
|
||||
|
||||
// The only one required function to make that a custom Response dispatcher.
|
||||
func (r testCustomResult) Dispatch(ctx context.Context) {
|
||||
func (r testCustomResult) Dispatch(ctx iris.Context) {
|
||||
_, _ = ctx.HTML(r.HTML)
|
||||
}
|
||||
|
||||
@@ -70,7 +72,7 @@ func GetCustomStructWithContentType() (testCustomStruct, string) {
|
||||
return testCustomStruct{"Iris", 2}, "text/xml"
|
||||
}
|
||||
|
||||
func GetCustomStructWithError(ctx context.Context) (s testCustomStruct, err error) {
|
||||
func GetCustomStructWithError(ctx iris.Context) (s testCustomStruct, err error) {
|
||||
s = testCustomStruct{"Iris", 2}
|
||||
if ctx.URLParamExists("err") {
|
||||
err = errors.New("omit return of testCustomStruct and fire error")
|
||||
@@ -86,7 +88,7 @@ type err struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func (e err) Dispatch(ctx context.Context) {
|
||||
func (e err) Dispatch(ctx iris.Context) {
|
||||
// write the status code based on the err's StatusCode.
|
||||
ctx.StatusCode(e.Status)
|
||||
// send to the client the whole object as json
|
||||
@@ -204,3 +206,55 @@ func TestFuncResult(t *testing.T) {
|
||||
e.GET("/custom/nil/struct").Expect().
|
||||
Status(iris.StatusOK).ContentType(context.ContentJSONHeaderValue).Body().Empty()
|
||||
}
|
||||
|
||||
type (
|
||||
testPreflightRequest struct {
|
||||
FailCode int `json:"fail_code"` // for the shake of the test.
|
||||
}
|
||||
|
||||
testPreflightResponse struct {
|
||||
Code int
|
||||
Message string
|
||||
}
|
||||
)
|
||||
|
||||
func (r testPreflightResponse) Preflight(ctx iris.Context) error {
|
||||
if r.Code == httptest.StatusInternalServerError {
|
||||
return fmt.Errorf("custom error")
|
||||
}
|
||||
|
||||
ctx.StatusCode(r.Code)
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestPreflightResult(t *testing.T) {
|
||||
app := iris.New()
|
||||
c := New()
|
||||
handler := c.Handler(func(in testPreflightRequest) testPreflightResponse {
|
||||
return testPreflightResponse{Code: in.FailCode, Message: http.StatusText(in.FailCode)}
|
||||
})
|
||||
app.Post("/", handler)
|
||||
handler2 := c.Handler(func(in testInput) (int, testOutput) {
|
||||
return httptest.StatusAccepted, testOutput{Name: in.Name}
|
||||
})
|
||||
app.Post("/alternative", handler2)
|
||||
|
||||
e := httptest.New(t, app)
|
||||
|
||||
expected1 := testPreflightResponse{Code: httptest.StatusOK, Message: "OK"}
|
||||
e.POST("/").WithJSON(testPreflightRequest{FailCode: expected1.Code}).
|
||||
Expect().Status(httptest.StatusOK).JSON().Equal(expected1)
|
||||
|
||||
expected2 := testPreflightResponse{Code: httptest.StatusBadRequest, Message: "Bad Request"}
|
||||
e.POST("/").WithJSON(testPreflightRequest{FailCode: expected2.Code}).
|
||||
Expect().Status(httptest.StatusBadRequest).JSON().Equal(expected2)
|
||||
|
||||
// Test error returned from Preflight.
|
||||
e.POST("/").WithJSON(testPreflightRequest{FailCode: httptest.StatusInternalServerError}).
|
||||
Expect().Status(httptest.StatusBadRequest).Body().Equal("custom error")
|
||||
|
||||
// Can be done without Preflight as the second output argument can be a status code.
|
||||
expected4 := testOutput{Name: "my_name"}
|
||||
e.POST("/alternative").WithJSON(testInput{expected4.Name}).
|
||||
Expect().Status(httptest.StatusAccepted).JSON().Equal(expected4)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user