1
0
mirror of https://github.com/kataras/iris.git synced 2025-12-27 23:07:03 +00:00

add examples for read using custom decoder per type, read using custom decoder via iris#UnmarshalerFunc and to complete it add an example for the context#ReadXML.

Former-commit-id: 536b1780f12d0b9d9ce9aa976a0f95f18634ec2d
This commit is contained in:
Gerasimos Maropoulos
2018-03-08 05:21:16 +02:00
parent 1a4803307d
commit 83c4b7f52d
14 changed files with 314 additions and 34 deletions

View File

@@ -318,8 +318,11 @@ You can serve [quicktemplate](https://github.com/valyala/quicktemplate) and [her
### How to Read from `context.Request() *http.Request`
- [Bind JSON](http_request/read-json/main.go)
- [Bind Form](http_request/read-form/main.go)
- [Read JSON](http_request/read-json/main.go)
- [Read XML](http_request/read-xml/main.go)
- [Read Form](http_request/read-form/main.go)
- [Read Custom per type](http_request/read-custom-per-type/main.go)
- [Read Custom via Unmarshaler](http_request/read-custom-via-unmarshaler/main.go)
- [Upload/Read File](http_request/upload-file/main.go)
- [Upload multiple files with an easy way](http_request/upload-files/main.go)

View File

@@ -0,0 +1,65 @@
package main
import (
"gopkg.in/yaml.v2"
"github.com/kataras/iris"
)
func main() {
app := newApp()
// use Postman or whatever to do a POST request
// (however you are always free to use app.Get and GET http method requests to read body of course)
// to the http://localhost:8080 with RAW BODY:
/*
addr: localhost:8080
serverName: Iris
*/
//
// The response should be:
// Received: main.config{Addr:"localhost:8080", ServerName:"Iris"}
app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed), iris.WithOptimizations)
}
func newApp() *iris.Application {
app := iris.New()
app.Post("/", handler)
return app
}
// simple yaml stuff, read more at https://github.com/go-yaml/yaml
type config struct {
Addr string `yaml:"addr"`
ServerName string `yaml:"serverName"`
}
// Decode implements the `kataras/iris/context#BodyDecoder` optional interface
// that any go type can implement in order to be self-decoded when reading the request's body.
func (c *config) Decode(body []byte) error {
return yaml.Unmarshal(body, c)
}
func handler(ctx iris.Context) {
var c config
//
// Note:
// second parameter is nil because our &c implements the `context#BodyDecoder`
// which has a priority over the context#Unmarshaler (which can be a more global option for reading request's body)
// see the `http_request/read-custom-via-unmarshaler/main.go` example to learn how to use the context#Unmarshaler too.
//
// Note 2:
// If you need to read the body again for any reason
// you should disable the body consumption via `app.Run(..., iris.WithoutBodyConsumptionOnUnmarshal)`.
//
if err := ctx.UnmarshalBody(&c, nil); err != nil {
ctx.StatusCode(iris.StatusBadRequest)
ctx.WriteString(err.Error())
return
}
ctx.Writef("Received: %#+v", c)
}

View File

@@ -0,0 +1,17 @@
package main
import (
"testing"
"github.com/kataras/iris/httptest"
)
func TestReadCustomPerType(t *testing.T) {
app := newApp()
e := httptest.New(t, app)
expectedResponse := `Received: main.config{Addr:"localhost:8080", ServerName:"Iris"}`
e.POST("/").WithText("addr: localhost:8080\nserverName: Iris").Expect().
Status(httptest.StatusOK).Body().Equal(expectedResponse)
}

View File

@@ -0,0 +1,73 @@
package main
import (
"gopkg.in/yaml.v2"
"github.com/kataras/iris"
)
func main() {
app := newApp()
// use Postman or whatever to do a POST request
// (however you are always free to use app.Get and GET http method requests to read body of course)
// to the http://localhost:8080 with RAW BODY:
/*
addr: localhost:8080
serverName: Iris
*/
//
// The response should be:
// Received: main.config{Addr:"localhost:8080", ServerName:"Iris"}
app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed), iris.WithOptimizations)
}
func newApp() *iris.Application {
app := iris.New()
app.Post("/", handler)
return app
}
// simple yaml stuff, read more at https://github.com/go-yaml/yaml
type config struct {
Addr string `yaml:"addr"`
ServerName string `yaml:"serverName"`
}
/*
type myBodyDecoder struct{}
var DefaultBodyDecoder = myBodyDecoder{}
// Implements the `kataras/iris/context#Unmarshaler` but at our example
// we will use the simplest `context#UnmarshalerFunc` to pass just the yaml.Unmarshal.
//
// Can be used as: ctx.UnmarshalBody(&c, DefaultBodyDecoder)
func (r *myBodyDecoder) Unmarshal(data []byte, outPtr interface{}) error {
return yaml.Unmarshal(data, outPtr)
}
*/
func handler(ctx iris.Context) {
var c config
//
// Note:
// yaml.Unmarshal already implements the `context#Unmarshaler`
// so we can use it directly, like the json.Unmarshal(ctx.ReadJSON), xml.Unmarshal(ctx.ReadXML)
// and every library which follows the best practises and is aligned with the Go standards.
//
// Note 2:
// If you need to read the body again for any reason
// you should disable the body consumption via `app.Run(..., iris.WithoutBodyConsumptionOnUnmarshal)`.
//
if err := ctx.UnmarshalBody(&c, iris.UnmarshalerFunc(yaml.Unmarshal)); err != nil {
ctx.StatusCode(iris.StatusBadRequest)
ctx.WriteString(err.Error())
return
}
ctx.Writef("Received: %#+v", c)
}

View File

@@ -0,0 +1,17 @@
package main
import (
"testing"
"github.com/kataras/iris/httptest"
)
func TestReadCustomViaUnmarshaler(t *testing.T) {
app := newApp()
e := httptest.New(t, app)
expectedResponse := `Received: main.config{Addr:"localhost:8080", ServerName:"Iris"}`
e.POST("/").WithText("addr: localhost:8080\nserverName: Iris").Expect().
Status(httptest.StatusOK).Body().Equal(expectedResponse)
}

View File

@@ -11,16 +11,18 @@ type Company struct {
}
func MyHandler(ctx iris.Context) {
c := &Company{}
if err := ctx.ReadJSON(c); err != nil {
var c Company
if err := ctx.ReadJSON(&c); err != nil {
ctx.StatusCode(iris.StatusBadRequest)
ctx.WriteString(err.Error())
return
}
ctx.Writef("Received: %#v\n", c)
ctx.Writef("Received: %#+v\n", c)
}
// simple json stuff, read more at https://golang.org/pkg/encoding/json
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
@@ -55,9 +57,9 @@ func main() {
"Other": "Something here"
}
*/
// and Content-Type to application/json
// and Content-Type to application/json (optionally but good practise)
//
// The response should be:
// Received: &main.Company{Name:"iris-Go", City:"New York", Other:"Something here"}
app.Run(iris.Addr(":8080"))
// Received: main.Company{Name:"iris-Go", City:"New York", Other:"Something here"}
app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed), iris.WithOptimizations)
}

View File

@@ -0,0 +1,50 @@
package main
import (
"encoding/xml"
"github.com/kataras/iris"
)
func main() {
app := newApp()
// use Postman or whatever to do a POST request
// to the http://localhost:8080 with RAW BODY:
/*
<person name="Winston Churchill" age="90">
<description>Description of this person, the body of this inner element.</description>
</person>
*/
// and Content-Type to application/xml (optionally but good practise)
//
// The response should be:
// Received: main.person{XMLName:xml.Name{Space:"", Local:"person"}, Name:"Winston Churchill", Age:90, Description:"Description of this person, the body of this inner element."}
app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed), iris.WithOptimizations)
}
func newApp() *iris.Application {
app := iris.New()
app.Post("/", handler)
return app
}
// simple xml stuff, read more at https://golang.org/pkg/encoding/xml
type person struct {
XMLName xml.Name `xml:"person"` // element name
Name string `xml:"name,attr"` // ,attr for attribute.
Age int `xml:"age,attr"` // ,attr attribute.
Description string `xml:"description"` // inner element name, value is its body.
}
func handler(ctx iris.Context) {
var p person
if err := ctx.ReadXML(&p); err != nil {
ctx.StatusCode(iris.StatusBadRequest)
ctx.WriteString(err.Error())
return
}
ctx.Writef("Received: %#+v", p)
}

View File

@@ -0,0 +1,18 @@
package main
import (
"testing"
"github.com/kataras/iris/httptest"
)
func TestReadXML(t *testing.T) {
app := newApp()
e := httptest.New(t, app)
expectedResponse := `Received: main.person{XMLName:xml.Name{Space:"", Local:"person"}, Name:"Winston Churchill", Age:90, Description:"Description of this person, the body of this inner element."}`
send := `<person name="Winston Churchill" age="90"><description>Description of this person, the body of this inner element.</description></person>`
e.POST("/").WithText(send).Expect().
Status(httptest.StatusOK).Body().Equal(expectedResponse)
}

View File

@@ -2,7 +2,6 @@ package main
import (
"bytes"
"log"
"github.com/kataras/iris/_examples/http_responsewriter/herotemplate/template"
@@ -13,11 +12,15 @@ import (
// $ go run app.go
//
// Read more at https://github.com/shiyanhui/hero/hero
func main() {
app := iris.New()
app.Get("/users", func(ctx iris.Context) {
ctx.Gzip(true)
ctx.ContentType("text/html")
var userList = []string{
"Alice",
"Bob",
@@ -25,30 +28,27 @@ func main() {
}
// Had better use buffer sync.Pool.
// Hero exports GetBuffer and PutBuffer for this.
// Hero(github.com/shiyanhui/hero/hero) exports GetBuffer and PutBuffer for this.
//
// buffer := hero.GetBuffer()
// defer hero.PutBuffer(buffer)
buffer := new(bytes.Buffer)
template.UserList(userList, buffer)
if _, err := ctx.Write(buffer.Bytes()); err != nil {
log.Printf("ERR: %s\n", err)
}
})
app.Get("/users2", func(ctx iris.Context) {
var userList = []string{
"Alice",
"Bob",
"Tom",
}
// buffer := new(bytes.Buffer)
// template.UserList(userList, buffer)
// ctx.Write(buffer.Bytes())
// using an io.Writer for automatic buffer management (i.e. hero built-in buffer pool),
// iris context implements the io.Writer by its ResponseWriter
// which is an enhanced version of the standard http.ResponseWriter
// but still 100% compatible.
template.UserListToWriter(userList, ctx)
// but still 100% compatible, GzipResponseWriter too:
// _, err := template.UserListToWriter(userList, ctx.GzipResponseWriter())
buffer := new(bytes.Buffer)
template.UserList(userList, buffer)
_, err := ctx.Write(buffer.Bytes())
if err != nil {
ctx.StatusCode(iris.StatusInternalServerError)
ctx.WriteString(err.Error())
}
})
app.Run(iris.Addr(":8080"))

View File

@@ -58,15 +58,11 @@ func (v *pageView) increment() {
}
func (v *pageView) decrement() {
oldCount := v.count
if oldCount > 0 {
atomic.StoreUint64(&v.count, oldCount-1)
}
atomic.AddUint64(&v.count, ^uint64(0))
}
func (v *pageView) getCount() uint64 {
val := atomic.LoadUint64(&v.count)
return val
return atomic.LoadUint64(&v.count)
}
type (