mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 18:51:03 +01:00
add content type and response text to the Controller 💯
Former-commit-id: 99cde0a445027b10839155501a7918732a783af3
This commit is contained in:
parent
fe94840929
commit
d7ec0d4416
|
@ -16,9 +16,9 @@ func main() {
|
||||||
app.Use(logger.New())
|
app.Use(logger.New())
|
||||||
|
|
||||||
// Method: GET
|
// Method: GET
|
||||||
// Resource: http://localhost:8080/
|
// Resource: http://localhost:8080
|
||||||
app.Handle("GET", "/", func(ctx iris.Context) {
|
app.Handle("GET", "/", func(ctx iris.Context) {
|
||||||
ctx.HTML("<b>Welcome!</b>")
|
ctx.HTML("<h1>Welcome</h1>")
|
||||||
})
|
})
|
||||||
|
|
||||||
// same as app.Handle("GET", "/ping", [...])
|
// same as app.Handle("GET", "/ping", [...])
|
||||||
|
@ -31,7 +31,7 @@ func main() {
|
||||||
// Method: GET
|
// Method: GET
|
||||||
// Resource: http://localhost:8080/hello
|
// Resource: http://localhost:8080/hello
|
||||||
app.Get("/hello", func(ctx iris.Context) {
|
app.Get("/hello", func(ctx iris.Context) {
|
||||||
ctx.JSON(iris.Map{"message": "Hello iris web framework."})
|
ctx.JSON(iris.Map{"message": "Hello Iris!"})
|
||||||
})
|
})
|
||||||
|
|
||||||
// http://localhost:8080
|
// http://localhost:8080
|
||||||
|
|
|
@ -35,9 +35,7 @@ func main() {
|
||||||
app.Use(recover.New())
|
app.Use(recover.New())
|
||||||
app.Use(logger.New())
|
app.Use(logger.New())
|
||||||
|
|
||||||
app.Controller("/", new(IndexController))
|
app.Controller("/", new(ExampleController))
|
||||||
app.Controller("/ping", new(PingController))
|
|
||||||
app.Controller("/hello", new(HelloController))
|
|
||||||
|
|
||||||
// http://localhost:8080
|
// http://localhost:8080
|
||||||
// http://localhost:8080/ping
|
// http://localhost:8080/ping
|
||||||
|
@ -45,63 +43,50 @@ func main() {
|
||||||
app.Run(iris.Addr(":8080"))
|
app.Run(iris.Addr(":8080"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// IndexController serves the "/".
|
// ExampleController serves the "/", "/ping" and "/hello".
|
||||||
type IndexController struct {
|
type ExampleController struct {
|
||||||
// if you build with go1.8 you have to use the mvc package, `mvc.Controller` instead.
|
// if you build with go1.8 you have to use the mvc package, `mvc.Controller` instead.
|
||||||
iris.Controller
|
iris.Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get serves
|
// Get serves
|
||||||
// Method: GET
|
// Method: GET
|
||||||
// Resource: http://localhost:8080/
|
// Resource: http://localhost:8080
|
||||||
func (c *IndexController) Get() {
|
func (c *ExampleController) Get() {
|
||||||
c.Ctx.HTML("<b>Welcome!</b>")
|
c.ContentType = "text/html"
|
||||||
|
c.Text = "<h1>Welcome!</h1>"
|
||||||
}
|
}
|
||||||
|
|
||||||
// PingController serves the "/ping".
|
// GetPing serves
|
||||||
type PingController struct {
|
|
||||||
iris.Controller
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get serves
|
|
||||||
// Method: GET
|
// Method: GET
|
||||||
// Resource: http://localhost:8080/ping
|
// Resource: http://localhost:8080/ping
|
||||||
func (c *PingController) Get() {
|
func (c *ExampleController) GetPing() {
|
||||||
c.Ctx.WriteString("pong")
|
c.Text = "pong"
|
||||||
}
|
}
|
||||||
|
|
||||||
// HelloController serves the "/hello".
|
// GetHello serves
|
||||||
type HelloController struct {
|
|
||||||
iris.Controller
|
|
||||||
}
|
|
||||||
|
|
||||||
type myJSONData struct {
|
|
||||||
Message string `json:"message"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get serves
|
|
||||||
// Method: GET
|
// Method: GET
|
||||||
// Resource: http://localhost:8080/hello
|
// Resource: http://localhost:8080/hello
|
||||||
func (c *HelloController) Get() {
|
func (c *ExampleController) GetHello() {
|
||||||
c.Ctx.JSON(myJSONData{"Hello iris web framework."})
|
c.Ctx.JSON(iris.Map{"message": "Hello Iris!"})
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Can use more than one, the factory will make sure
|
/* Can use more than one, the factory will make sure
|
||||||
that the correct http methods are being registered for each route
|
that the correct http methods are being registered for each route
|
||||||
for this controller, uncomment these if you want:
|
for this controller, uncomment these if you want:
|
||||||
|
|
||||||
func (c *HelloController) Post() {}
|
func (c *ExampleController) Post() {}
|
||||||
func (c *HelloController) Put() {}
|
func (c *ExampleController) Put() {}
|
||||||
func (c *HelloController) Delete() {}
|
func (c *ExampleController) Delete() {}
|
||||||
func (c *HelloController) Connect() {}
|
func (c *ExampleController) Connect() {}
|
||||||
func (c *HelloController) Head() {}
|
func (c *ExampleController) Head() {}
|
||||||
func (c *HelloController) Patch() {}
|
func (c *ExampleController) Patch() {}
|
||||||
func (c *HelloController) Options() {}
|
func (c *ExampleController) Options() {}
|
||||||
func (c *HelloController) Trace() {}
|
func (c *ExampleController) Trace() {}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
func (c *HelloController) All() {}
|
func (c *ExampleController) All() {}
|
||||||
// OR
|
// OR
|
||||||
func (c *HelloController) Any() {}
|
func (c *ExampleController) Any() {}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1366,12 +1366,21 @@ func (ctx *context) FormFile(key string) (multipart.File, *multipart.FileHeader,
|
||||||
func (ctx *context) Redirect(urlToRedirect string, statusHeader ...int) {
|
func (ctx *context) Redirect(urlToRedirect string, statusHeader ...int) {
|
||||||
ctx.StopExecution()
|
ctx.StopExecution()
|
||||||
|
|
||||||
httpStatus := http.StatusFound // a 'temporary-redirect-like' which works better than for our purpose
|
// get the previous status code given by the end-developer.
|
||||||
if len(statusHeader) > 0 && statusHeader[0] > 0 {
|
status := ctx.GetStatusCode()
|
||||||
httpStatus = statusHeader[0]
|
if len(statusHeader) > 0 {
|
||||||
|
// check if status code is passed via receivers.
|
||||||
|
if s := statusHeader[0]; s > 0 {
|
||||||
|
status = s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if status == 0 {
|
||||||
|
// if status remains zero then default it.
|
||||||
|
// a 'temporary-redirect-like' which works better than for our purpose
|
||||||
|
status = http.StatusFound
|
||||||
}
|
}
|
||||||
|
|
||||||
http.Redirect(ctx.writer, ctx.request, urlToRedirect, httpStatus)
|
http.Redirect(ctx.writer, ctx.request, urlToRedirect, status)
|
||||||
}
|
}
|
||||||
|
|
||||||
// +------------------------------------------------------------+
|
// +------------------------------------------------------------+
|
||||||
|
|
|
@ -169,7 +169,7 @@ func testTheRoutes(t *testing.T, tests []testRoute, debug bool) {
|
||||||
if method == "" {
|
if method == "" {
|
||||||
method = tt.method
|
method = tt.method
|
||||||
}
|
}
|
||||||
ex := e.Request(tt.method, req.path)
|
ex := e.Request(method, req.path)
|
||||||
if req.subdomain != "" {
|
if req.subdomain != "" {
|
||||||
ex.WithURL("http://" + req.subdomain + ".localhost:8080")
|
ex.WithURL("http://" + req.subdomain + ".localhost:8080")
|
||||||
}
|
}
|
||||||
|
|
30
doc.go
30
doc.go
|
@ -163,10 +163,10 @@ Example code:
|
||||||
|
|
||||||
Listening and gracefully shutdown
|
Listening and gracefully shutdown
|
||||||
|
|
||||||
You can listen to a server using any type of net.Listener or http.Server instance.
|
You can start the server(s) listening to any type of `net.Listener` or even `http.Server` instance.
|
||||||
The method for initialization of the server should be passed at the end, via `Run` function.
|
The method for initialization of the server should be passed at the end, via `Run` function.
|
||||||
|
|
||||||
Below you'll read some usage examples:
|
Below you'll see some useful examples:
|
||||||
|
|
||||||
|
|
||||||
// Listening on tcp with network address 0.0.0.0:8080
|
// Listening on tcp with network address 0.0.0.0:8080
|
||||||
|
@ -190,13 +190,22 @@ Below you'll read some usage examples:
|
||||||
|
|
||||||
|
|
||||||
// Automatic TLS
|
// Automatic TLS
|
||||||
app.Run(iris.AutoTLS("localhost:443"))
|
app.Run(iris.AutoTLS(":443", "example.com", "admin@example.com"))
|
||||||
|
|
||||||
|
|
||||||
// UNIX socket
|
// UNIX socket
|
||||||
l, err := netutil.UNIX("/tmpl/srv.sock", 0666)
|
if errOs := os.Remove(socketFile); errOs != nil && !os.IsNotExist(errOs) {
|
||||||
|
app.Logger().Fatal(errOs)
|
||||||
|
}
|
||||||
|
|
||||||
|
l, err := net.Listen("unix", socketFile)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
app.Logger().Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = os.Chmod(socketFile, mode); err != nil {
|
||||||
|
app.Logger().Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
app.Run(iris.Listener(l))
|
app.Run(iris.Listener(l))
|
||||||
|
@ -454,7 +463,7 @@ Example code:
|
||||||
app.Any("/", handler)
|
app.Any("/", handler)
|
||||||
|
|
||||||
func handler(ctx iris.Context){
|
func handler(ctx iris.Context){
|
||||||
ctx.Writef("Hello from method: %s and path: %s", ctx.Method(), ctx.Path())
|
ctx.Writef("Hello from method: %s and path: %s", ctx.Method(), ctx.Path())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -471,15 +480,12 @@ A group can have a nested group too.
|
||||||
Example code:
|
Example code:
|
||||||
|
|
||||||
|
|
||||||
users:= app.Party("/users", myAuthHandler)
|
users := app.Party("/users", myAuthMiddlewareHandler)
|
||||||
|
|
||||||
// http://myhost.com/users/42/profile
|
// http://myhost.com/users/42/profile
|
||||||
users.Get("/{userid:int}/profile", userProfileHandler)
|
users.Get("/{id:int}/profile", userProfileHandler)
|
||||||
// http://myhost.com/users/messages/1
|
// http://myhost.com/users/messages/1
|
||||||
users.Get("/inbox/{messageid:int}", userMessageHandler)
|
users.Get("/inbox/{id:int}", userMessageHandler)
|
||||||
|
|
||||||
app.Run(iris.Addr("myhost.com:80"))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Custom HTTP Errors
|
Custom HTTP Errors
|
||||||
|
|
|
@ -63,17 +63,18 @@ import (
|
||||||
// Look `core/router/APIBuilder#Controller` method too.
|
// Look `core/router/APIBuilder#Controller` method too.
|
||||||
type Controller struct {
|
type Controller struct {
|
||||||
// Name contains the current controller's full name.
|
// Name contains the current controller's full name.
|
||||||
|
//
|
||||||
|
// doesn't change on different paths.
|
||||||
Name string
|
Name string
|
||||||
|
|
||||||
// currentRoute is the current request context's route.
|
|
||||||
currentRoute context.RouteReadOnly
|
|
||||||
|
|
||||||
// contains the `Name` as different words, all lowercase,
|
// contains the `Name` as different words, all lowercase,
|
||||||
// without the "Controller" suffix if exists.
|
// without the "Controller" suffix if exists.
|
||||||
// we need this as field because the activator
|
// we need this as field because the activator
|
||||||
// we will not try to parse these if not needed
|
// we will not try to parse these if not needed
|
||||||
// it's up to the end-developer to call `RelPath()` or `RelTmpl()`
|
// it's up to the end-developer to call `RelPath()` or `RelTmpl()`
|
||||||
// which will result to fill them.
|
// which will result to fill them.
|
||||||
|
//
|
||||||
|
// doesn't change on different paths.
|
||||||
nameAsWords []string
|
nameAsWords []string
|
||||||
|
|
||||||
// relPath the "as assume" relative request path.
|
// relPath the "as assume" relative request path.
|
||||||
|
@ -81,10 +82,12 @@ type Controller struct {
|
||||||
// If UserController and request path is "/user/messages" then it's "/messages"
|
// If UserController and request path is "/user/messages" then it's "/messages"
|
||||||
// if UserPostController and request path is "/user/post" then it's "/"
|
// if UserPostController and request path is "/user/post" then it's "/"
|
||||||
// if UserProfile and request path is "/user/profile/likes" then it's "/likes"
|
// if UserProfile and request path is "/user/profile/likes" then it's "/likes"
|
||||||
|
//
|
||||||
|
// doesn't change on different paths.
|
||||||
relPath string
|
relPath string
|
||||||
|
|
||||||
// request path and its parameters, read-write.
|
// request path and its parameters, read-write.
|
||||||
// Path is the current request path.
|
// Path is the current request path, if changed then it redirects.
|
||||||
Path string
|
Path string
|
||||||
// Params are the request path's parameters, i.e
|
// Params are the request path's parameters, i.e
|
||||||
// for route like "/user/{id}" and request to "/user/42"
|
// for route like "/user/{id}" and request to "/user/42"
|
||||||
|
@ -101,13 +104,19 @@ type Controller struct {
|
||||||
// If UserController then it's "user/"
|
// If UserController then it's "user/"
|
||||||
// if UserPostController then it's "user/post/"
|
// if UserPostController then it's "user/post/"
|
||||||
// if UserProfile then it's "user/profile/".
|
// if UserProfile then it's "user/profile/".
|
||||||
|
//
|
||||||
|
// doesn't change on different paths.
|
||||||
relTmpl string
|
relTmpl string
|
||||||
|
|
||||||
// view read and write,
|
// view read and write,
|
||||||
// can be already set-ed by previous handlers as well.
|
// can be already set-ed by previous handlers as well.
|
||||||
Layout string
|
Layout string
|
||||||
Tmpl string
|
Tmpl string
|
||||||
Data map[string]interface{}
|
Data map[string]interface{}
|
||||||
|
|
||||||
|
ContentType string
|
||||||
|
Text string // or Text
|
||||||
|
|
||||||
// give access to the request context itself.
|
// give access to the request context itself.
|
||||||
Ctx context.Context
|
Ctx context.Context
|
||||||
}
|
}
|
||||||
|
@ -127,10 +136,7 @@ func (c *Controller) getNameWords() []string {
|
||||||
|
|
||||||
// Route returns the current request controller's context read-only access route.
|
// Route returns the current request controller's context read-only access route.
|
||||||
func (c *Controller) Route() context.RouteReadOnly {
|
func (c *Controller) Route() context.RouteReadOnly {
|
||||||
if c.currentRoute == nil {
|
return c.Ctx.GetCurrentRoute()
|
||||||
c.currentRoute = c.Ctx.GetCurrentRoute()
|
|
||||||
}
|
|
||||||
return c.currentRoute
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const slashStr = "/"
|
const slashStr = "/"
|
||||||
|
@ -208,6 +214,13 @@ func (c *Controller) RelTmpl() string {
|
||||||
return c.relTmpl
|
return c.relTmpl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write writes to the client via the context's ResponseWriter.
|
||||||
|
// Controller completes the `io.Writer` interface for the shake of ease.
|
||||||
|
func (c *Controller) Write(contents []byte) (int, error) {
|
||||||
|
c.tryWriteHeaders()
|
||||||
|
return c.Ctx.ResponseWriter().Write(contents)
|
||||||
|
}
|
||||||
|
|
||||||
// BeginRequest starts the main controller
|
// BeginRequest starts the main controller
|
||||||
// it initialize the Ctx and other fields.
|
// it initialize the Ctx and other fields.
|
||||||
//
|
//
|
||||||
|
@ -221,12 +234,26 @@ func (c *Controller) BeginRequest(ctx context.Context) {
|
||||||
c.Status = ctx.GetStatusCode()
|
c.Status = ctx.GetStatusCode()
|
||||||
// share values
|
// share values
|
||||||
c.Values = ctx.Values()
|
c.Values = ctx.Values()
|
||||||
// view
|
// view data for templates, remember
|
||||||
|
// each controller is a new instance, so
|
||||||
|
// checking for nil and then init those type of fields
|
||||||
|
// have no meaning.
|
||||||
c.Data = make(map[string]interface{}, 0)
|
c.Data = make(map[string]interface{}, 0)
|
||||||
|
|
||||||
// context itself
|
// context itself
|
||||||
c.Ctx = ctx
|
c.Ctx = ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Controller) tryWriteHeaders() {
|
||||||
|
if status := c.Status; status > 0 && status != c.Ctx.GetStatusCode() {
|
||||||
|
c.Ctx.StatusCode(status)
|
||||||
|
}
|
||||||
|
|
||||||
|
if contentType := c.ContentType; contentType != "" {
|
||||||
|
c.Ctx.ContentType(contentType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// EndRequest is the final method which will be executed
|
// EndRequest is the final method which will be executed
|
||||||
// before response sent.
|
// before response sent.
|
||||||
//
|
//
|
||||||
|
@ -236,25 +263,32 @@ func (c *Controller) BeginRequest(ctx context.Context) {
|
||||||
// It's called internally.
|
// It's called internally.
|
||||||
// End-Developer can ovveride it but still should be called at the end.
|
// End-Developer can ovveride it but still should be called at the end.
|
||||||
func (c *Controller) EndRequest(ctx context.Context) {
|
func (c *Controller) EndRequest(ctx context.Context) {
|
||||||
if path := c.Path; path != "" && path != ctx.Path() {
|
if ctx.ResponseWriter().Written() > 0 {
|
||||||
// then redirect
|
|
||||||
ctx.Redirect(path)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if status := c.Status; status > 0 && status != ctx.GetStatusCode() {
|
if path := c.Path; path != "" && path != ctx.Path() {
|
||||||
ctx.StatusCode(status)
|
// then redirect and exit.
|
||||||
|
ctx.Redirect(path, c.Status)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.tryWriteHeaders()
|
||||||
|
if response := c.Text; response != "" {
|
||||||
|
ctx.WriteString(response)
|
||||||
|
return // exit here
|
||||||
}
|
}
|
||||||
|
|
||||||
if view := c.Tmpl; view != "" {
|
if view := c.Tmpl; view != "" {
|
||||||
if layout := c.Layout; layout != "" {
|
if layout := c.Layout; layout != "" {
|
||||||
ctx.ViewLayout(layout)
|
ctx.ViewLayout(layout)
|
||||||
}
|
}
|
||||||
if data := c.Data; data != nil {
|
if data := c.Data; len(data) > 0 {
|
||||||
for k, v := range data {
|
for k, v := range data {
|
||||||
ctx.ViewData(k, v)
|
ctx.ViewData(k, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.View(view)
|
ctx.View(view)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user