add context.Protobuf, MsgPack, ReadProtobuf, ReadMsgPack methods

Former-commit-id: 39d547ecfb1516505a1eb76a12a1f6e9e4111962
This commit is contained in:
Gerasimos (Makis) Maropoulos 2020-04-08 16:48:22 +03:00
parent ee4213f72d
commit 837787104b
16 changed files with 215 additions and 40 deletions

View File

@ -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).

View File

@ -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)

View File

@ -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"

View File

@ -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:

View File

@ -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"

View File

@ -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")
} }

View 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")
}

View File

@ -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

View File

@ -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) {

View File

@ -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) {

View File

@ -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.
// //

View File

@ -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)
} }

View File

@ -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
View File

@ -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

View File

@ -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.

View File

@ -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: