-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add content negotiation feature, add context.ReadYAML and fix kataras…
- Loading branch information
Showing
15 changed files
with
985 additions
and
133 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package main | ||
|
||
import ( | ||
"github.com/kataras/iris" | ||
) | ||
|
||
func newApp() *iris.Application { | ||
app := iris.New() | ||
app.Post("/", handler) | ||
|
||
return app | ||
} | ||
|
||
// simple yaml stuff, read more at https://yaml.org/start.html | ||
type product struct { | ||
Invoice int `yaml:"invoice"` | ||
Tax float32 `yaml:"tax"` | ||
Total float32 `yaml:"total"` | ||
Comments string `yaml:"comments"` | ||
} | ||
|
||
func handler(ctx iris.Context) { | ||
var p product | ||
if err := ctx.ReadYAML(&p); err != nil { | ||
ctx.StatusCode(iris.StatusBadRequest) | ||
ctx.WriteString(err.Error()) | ||
return | ||
} | ||
|
||
ctx.Writef("Received: %#+v", p) | ||
} | ||
|
||
func main() { | ||
app := newApp() | ||
app.Run(iris.Addr(":8080")) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package main | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/kataras/iris/httptest" | ||
) | ||
|
||
func TestReadYAML(t *testing.T) { | ||
app := newApp() | ||
e := httptest.New(t, app) | ||
|
||
expectedResponse := `Received: main.product{Invoice:34843, Tax:251.42, Total:4443.52, Comments:"Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338."}` | ||
send := `invoice: 34843 | ||
tax : 251.42 | ||
total: 4443.52 | ||
comments: > | ||
Late afternoon is best. | ||
Backup contact is Nancy | ||
Billsmer @ 338-4338.` | ||
|
||
e.POST("/").WithHeader("Content-Type", "application/x-yaml").WithBytes([]byte(send)).Expect(). | ||
Status(httptest.StatusOK).Body().Equal(expectedResponse) | ||
} |
114 changes: 114 additions & 0 deletions
114
_examples/http_responsewriter/content-negotiation/main.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
// Package main contains three different ways to render content based on the client's accepted. | ||
package main | ||
|
||
import "github.com/kataras/iris" | ||
|
||
type testdata struct { | ||
Name string `json:"name" xml:"Name"` | ||
Age int `json:"age" xml:"Age"` | ||
} | ||
|
||
func newApp() *iris.Application { | ||
app := iris.New() | ||
app.Logger().SetLevel("debug") | ||
|
||
// app.Use(func(ctx iris.Context) { | ||
// requestedMime := ctx.URLParamDefault("type", "application/json") | ||
// | ||
// ctx.Negotiation().Accept.Override().MIME(requestedMime, nil) | ||
// ctx.Next() | ||
// }) | ||
|
||
app.Get("/resource", func(ctx iris.Context) { | ||
data := testdata{ | ||
Name: "test name", | ||
Age: 26, | ||
} | ||
|
||
// Server allows response only JSON and XML. These values | ||
// are compared with the clients mime needs. Iris comes with default mime types responses | ||
// but you can add a custom one by the `Negotiation().Mime(mime, content)` method, | ||
// same for the "accept". | ||
// You can also pass a custom ContentSelector(mime string) or ContentNegotiator to the | ||
// `Context.Negotiate` method if you want to perform more advanced things. | ||
// | ||
// | ||
// By-default the client accept mime is retrieved by the "Accept" header | ||
// Indeed you can override or update it by `Negotiation().Accept.XXX` i.e | ||
// ctx.Negotiation().Accept.Override().XML() | ||
// | ||
// All these values can change inside middlewares, the `Negotiation().Override()` and `.Accept.Override()` | ||
// can override any previously set values. | ||
// Order matters, if the client accepts anything (*/*) | ||
// then the first prioritized mime's response data will be rendered. | ||
ctx.Negotiation().JSON().XML() | ||
// Accept-Charset vs: | ||
ctx.Negotiation().Charset("utf-8", "iso-8859-7") | ||
// Alternatively you can define the content/data per mime type | ||
// anywhere in the handlers chain using the optional "v" variadic | ||
// input argument of the Context.Negotiation().JSON,XML,YAML,Binary,Text,HTML(...) and e.t.c | ||
// example (order matters): | ||
// ctx.Negotiation().JSON(data).XML(data).Any("content for */*") | ||
// ctx.Negotiate(nil) | ||
|
||
// if not nil passed in the `Context.Negotiate` method | ||
// then it overrides any contents made by the negotitation builder above. | ||
_, err := ctx.Negotiate(data) | ||
if err != nil { | ||
ctx.Writef("%v", err) | ||
} | ||
}) | ||
|
||
app.Get("/resource2", func(ctx iris.Context) { | ||
jsonAndXML := testdata{ | ||
Name: "test name", | ||
Age: 26, | ||
} | ||
|
||
// I prefer that one, as it gives me the freedom to modify | ||
// response data per accepted mime content type on middlewares as well. | ||
ctx.Negotiation(). | ||
JSON(jsonAndXML). | ||
XML(jsonAndXML). | ||
HTML("<h1>Test Name</h1><h2>Age 26</h2>") | ||
|
||
ctx.Negotiate(nil) | ||
}) | ||
|
||
app.Get("/resource3", func(ctx iris.Context) { | ||
// If that line is missing and the requested | ||
// mime type of content is */* or application/xml or application/json | ||
// then 406 Not Acceptable http error code will be rendered instead. | ||
// | ||
// We also add the "gzip" algorithm as an option to encode | ||
// resources on send. | ||
ctx.Negotiation().JSON().XML().HTML().EncodingGzip() | ||
|
||
jsonAndXML := testdata{ | ||
Name: "test name", | ||
Age: 26, | ||
} | ||
|
||
// Prefer that way instead of the '/resource2' above | ||
// if "iris.N" is a static one and can be declared | ||
// outside of a handler. | ||
ctx.Negotiate(iris.N{ | ||
// Text: for text/plain, | ||
// Markdown: for text/mardown, | ||
// Binary: for application/octet-stream, | ||
// YAML: for application/x-yaml, | ||
// JSONP: for application/javascript | ||
// Other: for anything else, | ||
JSON: jsonAndXML, // for application/json | ||
XML: jsonAndXML, // for application/xml or text/xml | ||
HTML: "<h1>Test Name</h1><h2>Age 26</h2>", // for text/html | ||
}) | ||
}) | ||
|
||
return app | ||
} | ||
|
||
func main() { | ||
app := newApp() | ||
app.Run(iris.Addr(":8080")) | ||
} |
78 changes: 78 additions & 0 deletions
78
_examples/http_responsewriter/content-negotiation/main_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package main | ||
|
||
import ( | ||
"bytes" | ||
"compress/gzip" | ||
"encoding/xml" | ||
"io/ioutil" | ||
"testing" | ||
|
||
"github.com/kataras/iris/httptest" | ||
) | ||
|
||
func TestContentNegotiation(t *testing.T) { | ||
var ( | ||
expectedJSONResponse = testdata{ | ||
Name: "test name", | ||
Age: 26, | ||
} | ||
expectedXMLResponse, _ = xml.Marshal(expectedJSONResponse) | ||
expectedHTMLResponse = "<h1>Test Name</h1><h2>Age 26</h2>" | ||
) | ||
|
||
e := httptest.New(t, newApp()) | ||
|
||
e.GET("/resource").WithHeader("Accept", "application/json"). | ||
Expect().Status(httptest.StatusOK). | ||
ContentType("application/json", "utf-8"). | ||
JSON().Equal(expectedJSONResponse) | ||
e.GET("/resource").WithHeader("Accept", "application/xml").WithHeader("Accept-Charset", "iso-8859-7"). | ||
Expect().Status(httptest.StatusOK). | ||
ContentType("application/xml", "iso-8859-7"). | ||
Body().Equal(string(expectedXMLResponse)) | ||
|
||
e.GET("/resource2").WithHeader("Accept", "application/json"). | ||
Expect().Status(httptest.StatusOK). | ||
ContentType("application/json", "utf-8"). | ||
JSON().Equal(expectedJSONResponse) | ||
e.GET("/resource2").WithHeader("Accept", "application/xml"). | ||
Expect().Status(httptest.StatusOK). | ||
ContentType("application/xml", "utf-8"). | ||
Body().Equal(string(expectedXMLResponse)) | ||
e.GET("/resource2").WithHeader("Accept", "text/html"). | ||
Expect().Status(httptest.StatusOK). | ||
ContentType("text/html", "utf-8"). | ||
Body().Equal(expectedHTMLResponse) | ||
|
||
e.GET("/resource3").WithHeader("Accept", "application/json"). | ||
Expect().Status(httptest.StatusOK). | ||
ContentType("application/json", "utf-8"). | ||
JSON().Equal(expectedJSONResponse) | ||
e.GET("/resource3").WithHeader("Accept", "application/xml"). | ||
Expect().Status(httptest.StatusOK). | ||
ContentType("application/xml", "utf-8"). | ||
Body().Equal(string(expectedXMLResponse)) | ||
|
||
// test html with "gzip" encoding algorithm. | ||
rawGzipResponse := e.GET("/resource3").WithHeader("Accept", "text/html"). | ||
WithHeader("Accept-Encoding", "gzip"). | ||
Expect().Status(httptest.StatusOK). | ||
ContentType("text/html", "utf-8"). | ||
ContentEncoding("gzip"). | ||
Body().Raw() | ||
|
||
zr, err := gzip.NewReader(bytes.NewReader([]byte(rawGzipResponse))) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
rawResponse, err := ioutil.ReadAll(zr) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
if expected, got := expectedHTMLResponse, string(rawResponse); expected != got { | ||
t.Fatalf("expected response to be:\n%s but got:\n%s", expected, got) | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.