From e9b10b14a3b4d2648c3b817fbe69a1bae1cdac4f Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Sat, 11 Apr 2020 00:55:31 +0300 Subject: [PATCH] add read-body example Former-commit-id: 7d7afa555e66fbe7edfa31203c26b4b550f336f4 --- _examples/README.md | 1 + _examples/http_request/read-body/main.go | 55 +++++++++++++++++++ _examples/http_request/read-body/main_test.go | 53 ++++++++++++++++++ context/context.go | 4 +- 4 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 _examples/http_request/read-body/main.go create mode 100644 _examples/http_request/read-body/main_test.go diff --git a/_examples/README.md b/_examples/README.md index 8bd7fbbf..abc39557 100644 --- a/_examples/README.md +++ b/_examples/README.md @@ -252,6 +252,7 @@ You can serve [quicktemplate](https://github.com/valyala/quicktemplate) and [her - [Read YAML](http_request/read-yaml/main.go) - [Read Form](http_request/read-form/main.go) - [Read Query](http_request/read-query/main.go) +- [Read Body](http_request/read-body/main.go) **NEW** - [Read Custom per type](http_request/read-custom-per-type/main.go) - [Read Custom via Unmarshaler](http_request/read-custom-via-unmarshaler/main.go) - [Read Many times](http_request/read-many/main.go) diff --git a/_examples/http_request/read-body/main.go b/_examples/http_request/read-body/main.go new file mode 100644 index 00000000..7f64cbc1 --- /dev/null +++ b/_examples/http_request/read-body/main.go @@ -0,0 +1,55 @@ +package main + +import ( + "github.com/kataras/iris/v12" +) + +func main() { + app := newApp() + // See main_test.go for usage. + app.Listen(":8080") +} + +func newApp() *iris.Application { + app := iris.New() + app.Use(setAllowedResponses) + + app.Post("/", readBody) + + return app +} + +func setAllowedResponses(ctx iris.Context) { + // Indicate that the Server can send JSON, XML, YAML and MessagePack for this request. + ctx.Negotiation().JSON().XML().YAML().MsgPack() + // Add more, allowed by the server format of responses, mime types here... + + // If client is missing an "Accept: " header then default it to JSON. + ctx.Negotiation().Accept.JSON() + + ctx.Next() +} + +type payload struct { + Message string `json:"message" xml:"message" msgpack:"message" yaml:"Message" url:"message" form:"message"` +} + +func readBody(ctx iris.Context) { + var p payload + + // Bind request body to "p" depending on the content-type that client sends the data, + // e.g. JSON, XML, YAML, MessagePack, Form, URL Query. + err := ctx.ReadBody(&p) + if err != nil { + ctx.StopWithProblem(iris.StatusBadRequest, + iris.NewProblem().Title("Parser issue").Detail(err.Error())) + return + } + + // For the shake of the example, log the received payload. + ctx.Application().Logger().Infof("Received: %#+v", p) + + // Send back the payload depending on the accept content type and accept-encoding of the client, + // e.g. JSON, XML and so on. + ctx.Negotiate(p) +} diff --git a/_examples/http_request/read-body/main_test.go b/_examples/http_request/read-body/main_test.go new file mode 100644 index 00000000..6522c9ab --- /dev/null +++ b/_examples/http_request/read-body/main_test.go @@ -0,0 +1,53 @@ +package main + +import ( + "testing" + + "github.com/kataras/iris/v12/httptest" +) + +func TestReadBodyAndNegotiate(t *testing.T) { + app := newApp() + + e := httptest.New(t, app) + + var ( + expectedPayload = payload{Message: "a message"} + expectedMsgPackPayload = "\x81\xa7message\xa9a message" + expectedXMLPayload = ` + a message + +` + expectedYAMLPayload = "Message: a message\n" + ) + + // Test send JSON and receive JSON. + e.POST("/").WithJSON(expectedPayload).Expect().Status(httptest.StatusOK). + JSON().Equal(expectedPayload) + + // Test send Form and receive XML. + e.POST("/").WithForm(expectedPayload). + WithHeader("Accept", "application/xml"). + Expect().Status(httptest.StatusOK). + Body().Equal(expectedXMLPayload) + + // Test send URL Query and receive MessagePack. + e.POST("/").WithQuery("message", expectedPayload.Message). + WithHeader("Accept", "application/msgpack"). + Expect().Status(httptest.StatusOK).ContentType("application/msgpack"). + Body().Equal(expectedMsgPackPayload) + + // Test send MessagePack and receive MessagePack. + e.POST("/").WithBytes([]byte(expectedMsgPackPayload)). + WithHeader("Content-Type", "application/msgpack"). + WithHeader("Accept", "application/msgpack"). + Expect().Status(httptest.StatusOK). + ContentType("application/msgpack").Body().Equal(expectedMsgPackPayload) + + // Test send YAML and receive YAML. + e.POST("/").WithBytes([]byte(expectedYAMLPayload)). + WithHeader("Content-Type", "application/x-yaml"). + WithHeader("Accept", "application/x-yaml"). + Expect().Status(httptest.StatusOK). + ContentType("application/x-yaml").Body().Equal(expectedYAMLPayload) +} diff --git a/context/context.go b/context/context.go index 1de7a848..e315b7ab 100644 --- a/context/context.go +++ b/context/context.go @@ -3621,7 +3621,7 @@ func WriteXML(writer io.Writer, v interface{}, options XML, optimize bool) (int, } if !optimize && options.Indent == "" { - options.Indent = " " + options.Indent = " " // Two spaces for XML is the default indentation when not optimized. } if indent := options.Indent; indent != "" { @@ -3941,7 +3941,7 @@ func (ctx *context) Negotiate(v interface{}) (int, error) { if contentType == "" { // If the server cannot serve any matching set, - // it can send back a 406 (Not Acceptable) error code. + // it SHOULD send back a 406 (Not Acceptable) error code. ctx.StatusCode(http.StatusNotAcceptable) return -1, ErrContentNotSupported }