mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 10:41:03 +01:00
add context.Protobuf, MsgPack, ReadProtobuf, ReadMsgPack methods
Former-commit-id: 39d547ecfb1516505a1eb76a12a1f6e9e4111962
This commit is contained in:
parent
ee4213f72d
commit
837787104b
|
@ -150,7 +150,7 @@ Prior to this version the `iris.Context` was the only one dependency that has be
|
||||||
| `float, float32, float64`, | |
|
| `float, float32, float64`, | |
|
||||||
| `bool`, | |
|
| `bool`, | |
|
||||||
| `slice` | [Path Parameter](https://github.com/kataras/iris/wiki/Routing-path-parameter-types) |
|
| `slice` | [Path Parameter](https://github.com/kataras/iris/wiki/Routing-path-parameter-types) |
|
||||||
| Struct | [Request Body](https://github.com/kataras/iris/tree/master/_examples/http_request) of `JSON`, `XML`, `YAML`, `Form`, `URL Query` |
|
| Struct | [Request Body](https://github.com/kataras/iris/tree/master/_examples/http_request) of `JSON`, `XML`, `YAML`, `Form`, `URL Query`, `Protobuf`, `MsgPack` |
|
||||||
|
|
||||||
Here is a preview of what the new Hero handlers look like:
|
Here is a preview of what the new Hero handlers look like:
|
||||||
|
|
||||||
|
@ -176,6 +176,10 @@ Other Improvements:
|
||||||
|
|
||||||
New Context Methods:
|
New Context Methods:
|
||||||
|
|
||||||
|
- `context.Protobuf(proto.Message)` sends protobuf to the client
|
||||||
|
- `context.MsgPack(interface{})` sends msgpack format data to the client
|
||||||
|
- `context.ReadProtobuf(ptr)` binds request body to a proto message
|
||||||
|
- `context.ReadMsgPack(ptr)` binds request body of a msgpack format to a struct
|
||||||
- `context.Defer(Handler)` works like `Party.Done` but for the request life-cycle.
|
- `context.Defer(Handler)` works like `Party.Done` but for the request life-cycle.
|
||||||
- `context.ReflectValue() []reflect.Value` stores and returns the `[]reflect.ValueOf(context)`
|
- `context.ReflectValue() []reflect.Value` stores and returns the `[]reflect.ValueOf(context)`
|
||||||
- `context.Controller() reflect.Value` returns the current MVC Controller value (when fired from inside a controller's method).
|
- `context.Controller() reflect.Value` returns the current MVC Controller value (when fired from inside a controller's method).
|
||||||
|
|
|
@ -248,6 +248,7 @@ You can serve [quicktemplate](https://github.com/valyala/quicktemplate) and [her
|
||||||
- [Read JSON](http_request/read-json/main.go)
|
- [Read JSON](http_request/read-json/main.go)
|
||||||
* [Struct Validation](http_request/read-json-struct-validation/main.go)
|
* [Struct Validation](http_request/read-json-struct-validation/main.go)
|
||||||
- [Read XML](http_request/read-xml/main.go)
|
- [Read XML](http_request/read-xml/main.go)
|
||||||
|
- [Read MsgPack](http_request/read-msgpack/main.go) **NEW**
|
||||||
- [Read YAML](http_request/read-yaml/main.go)
|
- [Read YAML](http_request/read-yaml/main.go)
|
||||||
- [Read Form](http_request/read-form/main.go)
|
- [Read Form](http_request/read-form/main.go)
|
||||||
- [Read Query](http_request/read-query/main.go)
|
- [Read Query](http_request/read-query/main.go)
|
||||||
|
|
|
@ -35,7 +35,7 @@ func main() {
|
||||||
DisableBodyConsumptionOnUnmarshal: false,
|
DisableBodyConsumptionOnUnmarshal: false,
|
||||||
DisableAutoFireStatusCode: false,
|
DisableAutoFireStatusCode: false,
|
||||||
TimeFormat: "Mon, 02 Jan 2006 15:04:05 GMT",
|
TimeFormat: "Mon, 02 Jan 2006 15:04:05 GMT",
|
||||||
Charset: "UTF-8",
|
Charset: "utf-8",
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -60,10 +60,10 @@ func main() {
|
||||||
// Prefix: "With", code editors will help you navigate through all
|
// Prefix: "With", code editors will help you navigate through all
|
||||||
// configuration options without even a glitch to the documentation.
|
// configuration options without even a glitch to the documentation.
|
||||||
|
|
||||||
app.Listen(":8080", iris.WithoutStartupLog, iris.WithCharset("UTF-8"))
|
app.Listen(":8080", iris.WithoutStartupLog, iris.WithCharset("utf-8"))
|
||||||
|
|
||||||
// or before run:
|
// or before run:
|
||||||
// app.Configure(iris.WithoutStartupLog, iris.WithCharset("UTF-8"))
|
// app.Configure(iris.WithoutStartupLog, iris.WithCharset("utf-8"))
|
||||||
// app.Listen(":8080")
|
// app.Listen(":8080")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -76,7 +76,7 @@ EnablePathEscape = false
|
||||||
FireMethodNotAllowed = true
|
FireMethodNotAllowed = true
|
||||||
DisableBodyConsumptionOnUnmarshal = false
|
DisableBodyConsumptionOnUnmarshal = false
|
||||||
TimeFormat = "Mon, 01 Jan 2006 15:04:05 GMT"
|
TimeFormat = "Mon, 01 Jan 2006 15:04:05 GMT"
|
||||||
Charset = "UTF-8"
|
Charset = "utf-8"
|
||||||
|
|
||||||
[Other]
|
[Other]
|
||||||
MyServerName = "iris"
|
MyServerName = "iris"
|
||||||
|
|
|
@ -21,7 +21,7 @@ func main() {
|
||||||
DisableBodyConsumptionOnUnmarshal: false,
|
DisableBodyConsumptionOnUnmarshal: false,
|
||||||
DisableAutoFireStatusCode: false,
|
DisableAutoFireStatusCode: false,
|
||||||
TimeFormat: "Mon, 02 Jan 2006 15:04:05 GMT",
|
TimeFormat: "Mon, 02 Jan 2006 15:04:05 GMT",
|
||||||
Charset: "UTF-8",
|
Charset: "utf-8",
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// or before Run:
|
// or before Run:
|
||||||
|
|
|
@ -3,7 +3,7 @@ EnablePathEscape = false
|
||||||
FireMethodNotAllowed = true
|
FireMethodNotAllowed = true
|
||||||
DisableBodyConsumptionOnUnmarshal = false
|
DisableBodyConsumptionOnUnmarshal = false
|
||||||
TimeFormat = "Mon, 01 Jan 2006 15:04:05 GMT"
|
TimeFormat = "Mon, 01 Jan 2006 15:04:05 GMT"
|
||||||
Charset = "UTF-8"
|
Charset = "utf-8"
|
||||||
|
|
||||||
[Other]
|
[Other]
|
||||||
MyServerName = "iris"
|
MyServerName = "iris"
|
||||||
|
|
|
@ -15,9 +15,9 @@ func main() {
|
||||||
// Prefix: "With", code editors will help you navigate through all
|
// Prefix: "With", code editors will help you navigate through all
|
||||||
// configuration options without even a glitch to the documentation.
|
// configuration options without even a glitch to the documentation.
|
||||||
|
|
||||||
app.Listen(":8080", iris.WithoutStartupLog, iris.WithCharset("UTF-8"))
|
app.Listen(":8080", iris.WithoutStartupLog, iris.WithCharset("utf-8"))
|
||||||
|
|
||||||
// or before run:
|
// or before run:
|
||||||
// app.Configure(iris.WithoutStartupLog, iris.WithCharset("UTF-8"))
|
// app.Configure(iris.WithoutStartupLog, iris.WithCharset("utf-8"))
|
||||||
// app.Listen(":8080")
|
// app.Listen(":8080")
|
||||||
}
|
}
|
||||||
|
|
38
_examples/http_request/read-msgpack/main.go
Normal file
38
_examples/http_request/read-msgpack/main.go
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "github.com/kataras/iris/v12"
|
||||||
|
|
||||||
|
// User example struct to bind to.
|
||||||
|
type User struct {
|
||||||
|
Firstname string `msgpack:"firstname"`
|
||||||
|
Lastname string `msgpack:"lastname"`
|
||||||
|
City string `msgpack:"city"`
|
||||||
|
Age int `msgpack:"age"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// readMsgPack reads a `User` from MsgPack post body.
|
||||||
|
func readMsgPack(ctx iris.Context) {
|
||||||
|
var u User
|
||||||
|
err := ctx.ReadMsgPack(&u)
|
||||||
|
if err != nil {
|
||||||
|
ctx.StatusCode(iris.StatusBadRequest)
|
||||||
|
ctx.WriteString(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Writef("Received: %#+v\n", u)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := iris.New()
|
||||||
|
app.Post("/", readMsgPack)
|
||||||
|
|
||||||
|
// POST: http://localhost:8080
|
||||||
|
//
|
||||||
|
// To run the example, use a tool like Postman:
|
||||||
|
// 1. Body: Binary
|
||||||
|
// 2. Select File, select the one from "_examples/http_responsewriter/write-rest" example.
|
||||||
|
// The output should be:
|
||||||
|
// Received: main.User{Firstname:"John", Lastname:"Doe", City:"Neither FBI knows!!!", Age:25}
|
||||||
|
app.Listen(":8080")
|
||||||
|
}
|
|
@ -7,12 +7,12 @@ import (
|
||||||
"github.com/kataras/iris/v12/context"
|
"github.com/kataras/iris/v12/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
// User bind struct
|
// User example struct for json and msgpack.
|
||||||
type User struct {
|
type User struct {
|
||||||
Firstname string `json:"firstname"`
|
Firstname string `json:"firstname" msgpack:"firstname"`
|
||||||
Lastname string `json:"lastname"`
|
Lastname string `json:"lastname" msgpack:"lastname"`
|
||||||
City string `json:"city"`
|
City string `json:"city" msgpack:"city"`
|
||||||
Age int `json:"age"`
|
Age int `json:"age" msgpack:"age"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExampleXML just a test struct to view represents xml content-type
|
// ExampleXML just a test struct to view represents xml content-type
|
||||||
|
@ -22,6 +22,12 @@ type ExampleXML struct {
|
||||||
Two string `xml:"two,attr"`
|
Two string `xml:"two,attr"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExampleYAML just a test struct to write yaml to the client.
|
||||||
|
type ExampleYAML struct {
|
||||||
|
Name string `yaml:"name"`
|
||||||
|
ServerAddr string `yaml:"ServerAddr"`
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := iris.New()
|
app := iris.New()
|
||||||
|
|
||||||
|
@ -36,7 +42,7 @@ func main() {
|
||||||
|
|
||||||
// Write
|
// Write
|
||||||
app.Get("/encode", func(ctx iris.Context) {
|
app.Get("/encode", func(ctx iris.Context) {
|
||||||
peter := User{
|
u := User{
|
||||||
Firstname: "John",
|
Firstname: "John",
|
||||||
Lastname: "Doe",
|
Lastname: "Doe",
|
||||||
City: "Neither FBI knows!!!",
|
City: "Neither FBI knows!!!",
|
||||||
|
@ -44,7 +50,7 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manually setting a content type: ctx.ContentType("application/javascript")
|
// Manually setting a content type: ctx.ContentType("application/javascript")
|
||||||
ctx.JSON(peter)
|
ctx.JSON(u)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Other content types,
|
// Other content types,
|
||||||
|
@ -74,6 +80,21 @@ func main() {
|
||||||
ctx.Markdown([]byte("# Hello Dynamic Markdown -- iris"))
|
ctx.Markdown([]byte("# Hello Dynamic Markdown -- iris"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
app.Get("/yaml", func(ctx iris.Context) {
|
||||||
|
ctx.YAML(ExampleYAML{Name: "Iris", ServerAddr: "localhost:8080"})
|
||||||
|
})
|
||||||
|
|
||||||
|
app.Get("/msgpack", func(ctx iris.Context) {
|
||||||
|
u := User{
|
||||||
|
Firstname: "John",
|
||||||
|
Lastname: "Doe",
|
||||||
|
City: "Neither FBI knows!!!",
|
||||||
|
Age: 25,
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.MsgPack(u)
|
||||||
|
})
|
||||||
|
|
||||||
// http://localhost:8080/decode
|
// http://localhost:8080/decode
|
||||||
// http://localhost:8080/encode
|
// http://localhost:8080/encode
|
||||||
//
|
//
|
||||||
|
@ -83,6 +104,7 @@ func main() {
|
||||||
// http://localhost:8080/jsonp
|
// http://localhost:8080/jsonp
|
||||||
// http://localhost:8080/xml
|
// http://localhost:8080/xml
|
||||||
// http://localhost:8080/markdown
|
// http://localhost:8080/markdown
|
||||||
|
// http://localhost:8080/msgpack
|
||||||
//
|
//
|
||||||
// `iris.WithOptimizations` is an optional configurator,
|
// `iris.WithOptimizations` is an optional configurator,
|
||||||
// if passed to the `Run` then it will ensure that the application
|
// if passed to the `Run` then it will ensure that the application
|
||||||
|
|
|
@ -83,7 +83,7 @@ func main() {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Listen for incoming HTTP/1.x & HTTP/2 clients on localhost port 8080.
|
// Listen for incoming HTTP/1.x & HTTP/2 clients on localhost port 8080.
|
||||||
app.Listen(":8080", iris.WithCharset("UTF-8"))
|
app.Listen(":8080", iris.WithCharset("utf-8"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func logThisMiddleware(ctx iris.Context) {
|
func logThisMiddleware(ctx iris.Context) {
|
||||||
|
|
|
@ -24,7 +24,7 @@ func main() {
|
||||||
app.Get("/", hi)
|
app.Get("/", hi)
|
||||||
|
|
||||||
// http://localhost:8080
|
// http://localhost:8080
|
||||||
app.Listen(":8080", iris.WithCharset("UTF-8")) // defaults to that but you can change it.
|
app.Listen(":8080", iris.WithCharset("utf-8")) // defaults to that but you can change it.
|
||||||
}
|
}
|
||||||
|
|
||||||
func hi(ctx iris.Context) {
|
func hi(ctx iris.Context) {
|
||||||
|
|
|
@ -803,7 +803,7 @@ type Configuration struct {
|
||||||
|
|
||||||
// Charset character encoding for various rendering
|
// Charset character encoding for various rendering
|
||||||
// used for templates and the rest of the responses
|
// used for templates and the rest of the responses
|
||||||
// Defaults to "UTF-8".
|
// Defaults to "utf-8".
|
||||||
Charset string `json:"charset,omitempty" yaml:"Charset" toml:"Charset"`
|
Charset string `json:"charset,omitempty" yaml:"Charset" toml:"Charset"`
|
||||||
|
|
||||||
// PostMaxMemory sets the maximum post data size
|
// PostMaxMemory sets the maximum post data size
|
||||||
|
@ -1109,7 +1109,7 @@ func DefaultConfiguration() Configuration {
|
||||||
DisableBodyConsumptionOnUnmarshal: false,
|
DisableBodyConsumptionOnUnmarshal: false,
|
||||||
DisableAutoFireStatusCode: false,
|
DisableAutoFireStatusCode: false,
|
||||||
TimeFormat: "Mon, 02 Jan 2006 15:04:05 GMT",
|
TimeFormat: "Mon, 02 Jan 2006 15:04:05 GMT",
|
||||||
Charset: "UTF-8",
|
Charset: "utf-8",
|
||||||
|
|
||||||
// PostMaxMemory is for post body max memory.
|
// PostMaxMemory is for post body max memory.
|
||||||
//
|
//
|
||||||
|
|
|
@ -148,7 +148,7 @@ FireMethodNotAllowed: true
|
||||||
EnableOptimizations: true
|
EnableOptimizations: true
|
||||||
DisableBodyConsumptionOnUnmarshal: true
|
DisableBodyConsumptionOnUnmarshal: true
|
||||||
TimeFormat: "Mon, 02 Jan 2006 15:04:05 GMT"
|
TimeFormat: "Mon, 02 Jan 2006 15:04:05 GMT"
|
||||||
Charset: "UTF-8"
|
Charset: "utf-8"
|
||||||
|
|
||||||
RemoteAddrHeaders:
|
RemoteAddrHeaders:
|
||||||
X-Real-Ip: true
|
X-Real-Ip: true
|
||||||
|
@ -192,7 +192,7 @@ Other:
|
||||||
t.Fatalf("error on TestConfigurationYAML: Expected TimeFormat %s but got %s", expected, c.TimeFormat)
|
t.Fatalf("error on TestConfigurationYAML: Expected TimeFormat %s but got %s", expected, c.TimeFormat)
|
||||||
}
|
}
|
||||||
|
|
||||||
if expected := "UTF-8"; c.Charset != expected {
|
if expected := "utf-8"; c.Charset != expected {
|
||||||
t.Fatalf("error on TestConfigurationYAML: Expected Charset %s but got %s", expected, c.Charset)
|
t.Fatalf("error on TestConfigurationYAML: Expected Charset %s but got %s", expected, c.Charset)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,7 +245,7 @@ FireMethodNotAllowed = true
|
||||||
EnableOptimizations = true
|
EnableOptimizations = true
|
||||||
DisableBodyConsumptionOnUnmarshal = true
|
DisableBodyConsumptionOnUnmarshal = true
|
||||||
TimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT"
|
TimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT"
|
||||||
Charset = "UTF-8"
|
Charset = "utf-8"
|
||||||
|
|
||||||
[RemoteAddrHeaders]
|
[RemoteAddrHeaders]
|
||||||
X-Real-Ip = true
|
X-Real-Ip = true
|
||||||
|
@ -291,7 +291,7 @@ Charset = "UTF-8"
|
||||||
t.Fatalf("error on TestConfigurationTOML: Expected TimeFormat %s but got %s", expected, c.TimeFormat)
|
t.Fatalf("error on TestConfigurationTOML: Expected TimeFormat %s but got %s", expected, c.TimeFormat)
|
||||||
}
|
}
|
||||||
|
|
||||||
if expected := "UTF-8"; c.Charset != expected {
|
if expected := "utf-8"; c.Charset != expected {
|
||||||
t.Fatalf("error on TestConfigurationTOML: Expected Charset %s but got %s", expected, c.Charset)
|
t.Fatalf("error on TestConfigurationTOML: Expected Charset %s but got %s", expected, c.Charset)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,10 +28,12 @@ import (
|
||||||
|
|
||||||
"github.com/Shopify/goreferrer"
|
"github.com/Shopify/goreferrer"
|
||||||
"github.com/fatih/structs"
|
"github.com/fatih/structs"
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
"github.com/iris-contrib/blackfriday"
|
"github.com/iris-contrib/blackfriday"
|
||||||
"github.com/iris-contrib/schema"
|
"github.com/iris-contrib/schema"
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
"github.com/microcosm-cc/bluemonday"
|
"github.com/microcosm-cc/bluemonday"
|
||||||
|
"github.com/vmihailenco/msgpack/v5"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -607,17 +609,21 @@ type Context interface {
|
||||||
//
|
//
|
||||||
// Example: https://github.com/kataras/iris/blob/master/_examples/http_request/read-yaml/main.go
|
// Example: https://github.com/kataras/iris/blob/master/_examples/http_request/read-yaml/main.go
|
||||||
ReadYAML(outPtr interface{}) error
|
ReadYAML(outPtr interface{}) error
|
||||||
// ReadForm binds the formObject with the form data
|
// ReadForm binds the request body of a form to the "formObject".
|
||||||
// it supports any kind of type, including custom structs.
|
// It supports any kind of type, including custom structs.
|
||||||
// It will return nothing if request data are empty.
|
// It will return nothing if request data are empty.
|
||||||
// The struct field tag is "form".
|
// The struct field tag is "form".
|
||||||
//
|
//
|
||||||
// Example: https://github.com/kataras/iris/blob/master/_examples/http_request/read-form/main.go
|
// Example: https://github.com/kataras/iris/blob/master/_examples/http_request/read-form/main.go
|
||||||
ReadForm(formObject interface{}) error
|
ReadForm(formObject interface{}) error
|
||||||
// ReadQuery binds the "ptr" with the url query string. The struct field tag is "url".
|
// ReadQuery binds url query to "ptr". The struct field tag is "url".
|
||||||
//
|
//
|
||||||
// Example: https://github.com/kataras/iris/blob/master/_examples/http_request/read-query/main.go
|
// Example: https://github.com/kataras/iris/blob/master/_examples/http_request/read-query/main.go
|
||||||
ReadQuery(ptr interface{}) error
|
ReadQuery(ptr interface{}) error
|
||||||
|
// ReadProtobuf binds the body to the "ptr" of a proto Message and returns any error.
|
||||||
|
ReadProtobuf(ptr proto.Message) error
|
||||||
|
// ReadMsgPack binds the request body of msgpack format to the "ptr" and returns any error.
|
||||||
|
ReadMsgPack(ptr interface{}) error
|
||||||
// +------------------------------------------------------------+
|
// +------------------------------------------------------------+
|
||||||
// | Body (raw) Writers |
|
// | Body (raw) Writers |
|
||||||
// +------------------------------------------------------------+
|
// +------------------------------------------------------------+
|
||||||
|
@ -815,6 +821,10 @@ type Context interface {
|
||||||
Markdown(markdownB []byte, options ...Markdown) (int, error)
|
Markdown(markdownB []byte, options ...Markdown) (int, error)
|
||||||
// YAML parses the "v" using the yaml parser and renders its result to the client.
|
// YAML parses the "v" using the yaml parser and renders its result to the client.
|
||||||
YAML(v interface{}) (int, error)
|
YAML(v interface{}) (int, error)
|
||||||
|
// Protobuf parses the "v" of proto Message and renders its result to the client.
|
||||||
|
Protobuf(v proto.Message) (int, error)
|
||||||
|
// MsgPack parses the "v" of msgpack format and renders its result to the client.
|
||||||
|
MsgPack(v interface{}) (int, error)
|
||||||
|
|
||||||
// +-----------------------------------------------------------------------+
|
// +-----------------------------------------------------------------------+
|
||||||
// | Content Νegotiation |
|
// | Content Νegotiation |
|
||||||
|
@ -2650,8 +2660,8 @@ func (ctx *context) ReadYAML(outPtr interface{}) error {
|
||||||
// A shortcut for the `schema#IsErrPath`.
|
// A shortcut for the `schema#IsErrPath`.
|
||||||
var IsErrPath = schema.IsErrPath
|
var IsErrPath = schema.IsErrPath
|
||||||
|
|
||||||
// ReadForm binds the formObject with the form data
|
// ReadForm binds the request body of a form to the "formObject".
|
||||||
// it supports any kind of type, including custom structs.
|
// It supports any kind of type, including custom structs.
|
||||||
// It will return nothing if request data are empty.
|
// It will return nothing if request data are empty.
|
||||||
// The struct field tag is "form".
|
// The struct field tag is "form".
|
||||||
//
|
//
|
||||||
|
@ -2665,7 +2675,7 @@ func (ctx *context) ReadForm(formObject interface{}) error {
|
||||||
return schema.DecodeForm(values, formObject)
|
return schema.DecodeForm(values, formObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadQuery binds the "ptr" with the url query string. The struct field tag is "url".
|
// ReadQuery binds url query to "ptr". The struct field tag is "url".
|
||||||
//
|
//
|
||||||
// Example: https://github.com/kataras/iris/blob/master/_examples/http_request/read-query/main.go
|
// Example: https://github.com/kataras/iris/blob/master/_examples/http_request/read-query/main.go
|
||||||
func (ctx *context) ReadQuery(ptr interface{}) error {
|
func (ctx *context) ReadQuery(ptr interface{}) error {
|
||||||
|
@ -2677,6 +2687,26 @@ func (ctx *context) ReadQuery(ptr interface{}) error {
|
||||||
return schema.DecodeQuery(values, ptr)
|
return schema.DecodeQuery(values, ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadProtobuf binds the body to the "ptr" of a proto Message and returns any error.
|
||||||
|
func (ctx *context) ReadProtobuf(ptr proto.Message) error {
|
||||||
|
rawData, err := ctx.GetBody()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return proto.Unmarshal(rawData, ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadMsgPack binds the request body of msgpack format to the "ptr" and returns any error.
|
||||||
|
func (ctx *context) ReadMsgPack(ptr interface{}) error {
|
||||||
|
rawData, err := ctx.GetBody()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return msgpack.Unmarshal(rawData, ptr)
|
||||||
|
}
|
||||||
|
|
||||||
// +------------------------------------------------------------+
|
// +------------------------------------------------------------+
|
||||||
// | Body (raw) Writers |
|
// | Body (raw) Writers |
|
||||||
// +------------------------------------------------------------+
|
// +------------------------------------------------------------+
|
||||||
|
@ -3140,6 +3170,12 @@ const (
|
||||||
ContentMarkdownHeaderValue = "text/markdown"
|
ContentMarkdownHeaderValue = "text/markdown"
|
||||||
// ContentYAMLHeaderValue header value for YAML data.
|
// ContentYAMLHeaderValue header value for YAML data.
|
||||||
ContentYAMLHeaderValue = "application/x-yaml"
|
ContentYAMLHeaderValue = "application/x-yaml"
|
||||||
|
// ContentProtobufHeaderValue header value for Protobuf messages data.
|
||||||
|
ContentProtobufHeaderValue = "application/x-protobuf"
|
||||||
|
// ContentMsgPackHeaderValue header value for MsgPack data.
|
||||||
|
ContentMsgPackHeaderValue = "application/msgpack"
|
||||||
|
// ContentMsgPack2HeaderValue alternative header value for MsgPack data.
|
||||||
|
ContentMsgPack2HeaderValue = "application/x-msgpack"
|
||||||
// ContentFormHeaderValue header value for post form data.
|
// ContentFormHeaderValue header value for post form data.
|
||||||
ContentFormHeaderValue = "application/x-www-form-urlencoded"
|
ContentFormHeaderValue = "application/x-www-form-urlencoded"
|
||||||
// ContentFormMultipartHeaderValue header value for post multipart form data.
|
// ContentFormMultipartHeaderValue header value for post multipart form data.
|
||||||
|
@ -3583,6 +3619,28 @@ func (ctx *context) YAML(v interface{}) (int, error) {
|
||||||
return ctx.Write(out)
|
return ctx.Write(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Protobuf parses the "v" of proto Message and renders its result to the client.
|
||||||
|
func (ctx *context) Protobuf(v proto.Message) (int, error) {
|
||||||
|
out, err := proto.Marshal(v)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.ContentType(ContentProtobufHeaderValue)
|
||||||
|
return ctx.Write(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgPack parses the "v" of msgpack format and renders its result to the client.
|
||||||
|
func (ctx *context) MsgPack(v interface{}) (int, error) {
|
||||||
|
out, err := msgpack.Marshal(v)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.ContentType(ContentMsgPackHeaderValue)
|
||||||
|
return ctx.Write(out)
|
||||||
|
}
|
||||||
|
|
||||||
// +-----------------------------------------------------------------------+
|
// +-----------------------------------------------------------------------+
|
||||||
// | Content Νegotiation |
|
// | Content Νegotiation |
|
||||||
// | https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation | |
|
// | https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation | |
|
||||||
|
@ -3628,11 +3686,13 @@ type N struct {
|
||||||
Markdown []byte
|
Markdown []byte
|
||||||
Binary []byte
|
Binary []byte
|
||||||
|
|
||||||
JSON interface{}
|
JSON interface{}
|
||||||
Problem Problem
|
Problem Problem
|
||||||
JSONP interface{}
|
JSONP interface{}
|
||||||
XML interface{}
|
XML interface{}
|
||||||
YAML interface{}
|
YAML interface{}
|
||||||
|
Protobuf interface{}
|
||||||
|
MsgPack interface{}
|
||||||
|
|
||||||
Other []byte // custom content types.
|
Other []byte // custom content types.
|
||||||
}
|
}
|
||||||
|
@ -3658,12 +3718,16 @@ func (n N) SelectContent(mime string) interface{} {
|
||||||
return n.XML
|
return n.XML
|
||||||
case ContentYAMLHeaderValue:
|
case ContentYAMLHeaderValue:
|
||||||
return n.YAML
|
return n.YAML
|
||||||
|
case ContentProtobufHeaderValue:
|
||||||
|
return n.Protobuf
|
||||||
|
case ContentMsgPackHeaderValue, ContentMsgPack2HeaderValue:
|
||||||
|
return n.MsgPack
|
||||||
default:
|
default:
|
||||||
return n.Other
|
return n.Other
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const negotiationContextKey = "_iris_negotiation_builder"
|
const negotiationContextKey = "iris.negotiation_builder"
|
||||||
|
|
||||||
// Negotiation creates once and returns the negotiation builder
|
// Negotiation creates once and returns the negotiation builder
|
||||||
// to build server-side available prioritized content
|
// to build server-side available prioritized content
|
||||||
|
@ -3706,7 +3770,7 @@ func parseHeader(headerValue string) []string {
|
||||||
// The "v" can be a single `N` struct value.
|
// The "v" can be a single `N` struct value.
|
||||||
// The "v" can be any value completes the `ContentSelector` interface.
|
// The "v" can be any value completes the `ContentSelector` interface.
|
||||||
// The "v" can be any value completes the `ContentNegotiator` interface.
|
// The "v" can be any value completes the `ContentNegotiator` interface.
|
||||||
// The "v" can be any value of struct(JSON, JSONP, XML, YAML) or
|
// The "v" can be any value of struct(JSON, JSONP, XML, YAML, Protobuf, MsgPack) or
|
||||||
// string(TEXT, HTML) or []byte(Markdown, Binary) or []byte with any matched mime type.
|
// string(TEXT, HTML) or []byte(Markdown, Binary) or []byte with any matched mime type.
|
||||||
//
|
//
|
||||||
// If the "v" is nil, the `Context.Negotitation()` builder's
|
// If the "v" is nil, the `Context.Negotitation()` builder's
|
||||||
|
@ -3791,6 +3855,15 @@ func (ctx *context) Negotiate(v interface{}) (int, error) {
|
||||||
return ctx.XML(v)
|
return ctx.XML(v)
|
||||||
case ContentYAMLHeaderValue:
|
case ContentYAMLHeaderValue:
|
||||||
return ctx.YAML(v)
|
return ctx.YAML(v)
|
||||||
|
case ContentProtobufHeaderValue:
|
||||||
|
msg, ok := v.(proto.Message)
|
||||||
|
if !ok {
|
||||||
|
return -1, ErrContentNotSupported
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.Protobuf(msg)
|
||||||
|
case ContentMsgPackHeaderValue, ContentMsgPack2HeaderValue:
|
||||||
|
return ctx.MsgPack(v)
|
||||||
default:
|
default:
|
||||||
// maybe "Other" or v is []byte or string but not a built-in framework mime,
|
// maybe "Other" or v is []byte or string but not a built-in framework mime,
|
||||||
// for custom content types,
|
// for custom content types,
|
||||||
|
@ -3966,6 +4039,32 @@ func (n *NegotiationBuilder) YAML(v ...interface{}) *NegotiationBuilder {
|
||||||
return n.MIME(ContentYAMLHeaderValue, content)
|
return n.MIME(ContentYAMLHeaderValue, content)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Protobuf registers the "application/x-protobuf" content type and, optionally,
|
||||||
|
// a value that `Context.Negotiate` will render
|
||||||
|
// when a client accepts the "application/x-protobuf" content type.
|
||||||
|
//
|
||||||
|
// Returns itself for recursive calls.
|
||||||
|
func (n *NegotiationBuilder) Protobuf(v ...interface{}) *NegotiationBuilder {
|
||||||
|
var content interface{}
|
||||||
|
if len(v) > 0 {
|
||||||
|
content = v[0]
|
||||||
|
}
|
||||||
|
return n.MIME(ContentProtobufHeaderValue, content)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgPack registers the "application/x-msgpack" and "application/msgpack" content types and, optionally,
|
||||||
|
// a value that `Context.Negotiate` will render
|
||||||
|
// when a client accepts one of the "application/x-msgpack" or "application/msgpack" content types.
|
||||||
|
//
|
||||||
|
// Returns itself for recursive calls.
|
||||||
|
func (n *NegotiationBuilder) MsgPack(v ...interface{}) *NegotiationBuilder {
|
||||||
|
var content interface{}
|
||||||
|
if len(v) > 0 {
|
||||||
|
content = v[0]
|
||||||
|
}
|
||||||
|
return n.MIME(ContentMsgPackHeaderValue+","+ContentMsgPack2HeaderValue, content)
|
||||||
|
}
|
||||||
|
|
||||||
// Any registers a wildcard that can match any client's accept content type.
|
// Any registers a wildcard that can match any client's accept content type.
|
||||||
//
|
//
|
||||||
// Returns itself for recursive calls.
|
// Returns itself for recursive calls.
|
||||||
|
|
5
go.mod
5
go.mod
|
@ -12,13 +12,14 @@ require (
|
||||||
github.com/etcd-io/bbolt v1.3.3
|
github.com/etcd-io/bbolt v1.3.3
|
||||||
github.com/fatih/structs v1.1.0
|
github.com/fatih/structs v1.1.0
|
||||||
github.com/gavv/httpexpect v2.0.0+incompatible
|
github.com/gavv/httpexpect v2.0.0+incompatible
|
||||||
|
github.com/golang/protobuf v1.3.5
|
||||||
github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38
|
github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38
|
||||||
github.com/hashicorp/go-version v1.2.0
|
github.com/hashicorp/go-version v1.2.0
|
||||||
github.com/iris-contrib/blackfriday v2.0.0+incompatible
|
github.com/iris-contrib/blackfriday v2.0.0+incompatible
|
||||||
github.com/iris-contrib/go.uuid v2.0.0+incompatible
|
github.com/iris-contrib/go.uuid v2.0.0+incompatible
|
||||||
|
github.com/iris-contrib/jade v1.1.3
|
||||||
github.com/iris-contrib/pongo2 v0.0.1
|
github.com/iris-contrib/pongo2 v0.0.1
|
||||||
github.com/iris-contrib/schema v0.0.1
|
github.com/iris-contrib/schema v0.0.1
|
||||||
github.com/iris-contrib/jade v1.1.3
|
|
||||||
github.com/json-iterator/go v1.1.9
|
github.com/json-iterator/go v1.1.9
|
||||||
github.com/kataras/golog v0.0.10
|
github.com/kataras/golog v0.0.10
|
||||||
github.com/kataras/neffos v0.0.14
|
github.com/kataras/neffos v0.0.14
|
||||||
|
@ -28,8 +29,8 @@ require (
|
||||||
github.com/microcosm-cc/bluemonday v1.0.2
|
github.com/microcosm-cc/bluemonday v1.0.2
|
||||||
github.com/ryanuber/columnize v2.1.0+incompatible
|
github.com/ryanuber/columnize v2.1.0+incompatible
|
||||||
github.com/schollz/closestmatch v2.1.0+incompatible
|
github.com/schollz/closestmatch v2.1.0+incompatible
|
||||||
|
github.com/vmihailenco/msgpack/v5 v5.0.0-alpha.2
|
||||||
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876
|
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876
|
||||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553
|
|
||||||
golang.org/x/text v0.3.2
|
golang.org/x/text v0.3.2
|
||||||
gopkg.in/ini.v1 v1.51.1
|
gopkg.in/ini.v1 v1.51.1
|
||||||
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2
|
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2
|
||||||
|
|
|
@ -7,6 +7,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/kataras/iris/v12/context"
|
"github.com/kataras/iris/v12/context"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// binding contains the Dependency and the Input, it's the result of a function or struct + dependencies.
|
// binding contains the Dependency and the Input, it's the result of a function or struct + dependencies.
|
||||||
|
@ -344,6 +346,14 @@ func payloadBinding(index int, typ reflect.Type) *binding {
|
||||||
err = ctx.ReadForm(ptr)
|
err = ctx.ReadForm(ptr)
|
||||||
case context.ContentJSONHeaderValue:
|
case context.ContentJSONHeaderValue:
|
||||||
err = ctx.ReadJSON(ptr)
|
err = ctx.ReadJSON(ptr)
|
||||||
|
case context.ContentProtobufHeaderValue:
|
||||||
|
if msg, ok := ptr.(proto.Message); ok {
|
||||||
|
err = ctx.ReadProtobuf(msg)
|
||||||
|
} else {
|
||||||
|
err = context.ErrContentNotSupported
|
||||||
|
}
|
||||||
|
case context.ContentMsgPackHeaderValue, context.ContentMsgPack2HeaderValue:
|
||||||
|
err = ctx.ReadMsgPack(ptr)
|
||||||
default:
|
default:
|
||||||
if ctx.Request().URL.RawQuery != "" {
|
if ctx.Request().URL.RawQuery != "" {
|
||||||
// try read from query.
|
// try read from query.
|
||||||
|
|
2
iris.go
2
iris.go
|
@ -965,7 +965,7 @@ func (app *Application) Listen(hostPort string, withOrWithout ...Configurator) e
|
||||||
// then create a new host and run it manually by `go NewHost(*http.Server).Serve/ListenAndServe` etc...
|
// then create a new host and run it manually by `go NewHost(*http.Server).Serve/ListenAndServe` etc...
|
||||||
// or use an already created host:
|
// or use an already created host:
|
||||||
// h := NewHost(*http.Server)
|
// h := NewHost(*http.Server)
|
||||||
// Run(Raw(h.ListenAndServe), WithCharset("UTF-8"), WithRemoteAddrHeader("CF-Connecting-IP"))
|
// Run(Raw(h.ListenAndServe), WithCharset("utf-8"), WithRemoteAddrHeader("CF-Connecting-IP"))
|
||||||
//
|
//
|
||||||
// The Application can go online with any type of server or iris's host with the help of
|
// The Application can go online with any type of server or iris's host with the help of
|
||||||
// the following runners:
|
// the following runners:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user