mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 10:41: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())
|
||||
|
||||
// Method: GET
|
||||
// Resource: http://localhost:8080/
|
||||
// Resource: http://localhost:8080
|
||||
app.Handle("GET", "/", func(ctx iris.Context) {
|
||||
ctx.HTML("<b>Welcome!</b>")
|
||||
ctx.HTML("<h1>Welcome</h1>")
|
||||
})
|
||||
|
||||
// same as app.Handle("GET", "/ping", [...])
|
||||
|
@ -31,7 +31,7 @@ func main() {
|
|||
// Method: GET
|
||||
// Resource: http://localhost:8080/hello
|
||||
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
|
||||
|
|
|
@ -35,9 +35,7 @@ func main() {
|
|||
app.Use(recover.New())
|
||||
app.Use(logger.New())
|
||||
|
||||
app.Controller("/", new(IndexController))
|
||||
app.Controller("/ping", new(PingController))
|
||||
app.Controller("/hello", new(HelloController))
|
||||
app.Controller("/", new(ExampleController))
|
||||
|
||||
// http://localhost:8080
|
||||
// http://localhost:8080/ping
|
||||
|
@ -45,63 +43,50 @@ func main() {
|
|||
app.Run(iris.Addr(":8080"))
|
||||
}
|
||||
|
||||
// IndexController serves the "/".
|
||||
type IndexController struct {
|
||||
// ExampleController serves the "/", "/ping" and "/hello".
|
||||
type ExampleController struct {
|
||||
// if you build with go1.8 you have to use the mvc package, `mvc.Controller` instead.
|
||||
iris.Controller
|
||||
}
|
||||
|
||||
// Get serves
|
||||
// Method: GET
|
||||
// Resource: http://localhost:8080/
|
||||
func (c *IndexController) Get() {
|
||||
c.Ctx.HTML("<b>Welcome!</b>")
|
||||
// Resource: http://localhost:8080
|
||||
func (c *ExampleController) Get() {
|
||||
c.ContentType = "text/html"
|
||||
c.Text = "<h1>Welcome!</h1>"
|
||||
}
|
||||
|
||||
// PingController serves the "/ping".
|
||||
type PingController struct {
|
||||
iris.Controller
|
||||
}
|
||||
|
||||
// Get serves
|
||||
// GetPing serves
|
||||
// Method: GET
|
||||
// Resource: http://localhost:8080/ping
|
||||
func (c *PingController) Get() {
|
||||
c.Ctx.WriteString("pong")
|
||||
func (c *ExampleController) GetPing() {
|
||||
c.Text = "pong"
|
||||
}
|
||||
|
||||
// HelloController serves the "/hello".
|
||||
type HelloController struct {
|
||||
iris.Controller
|
||||
}
|
||||
|
||||
type myJSONData struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// Get serves
|
||||
// GetHello serves
|
||||
// Method: GET
|
||||
// Resource: http://localhost:8080/hello
|
||||
func (c *HelloController) Get() {
|
||||
c.Ctx.JSON(myJSONData{"Hello iris web framework."})
|
||||
func (c *ExampleController) GetHello() {
|
||||
c.Ctx.JSON(iris.Map{"message": "Hello Iris!"})
|
||||
}
|
||||
|
||||
/* Can use more than one, the factory will make sure
|
||||
that the correct http methods are being registered for each route
|
||||
for this controller, uncomment these if you want:
|
||||
|
||||
func (c *HelloController) Post() {}
|
||||
func (c *HelloController) Put() {}
|
||||
func (c *HelloController) Delete() {}
|
||||
func (c *HelloController) Connect() {}
|
||||
func (c *HelloController) Head() {}
|
||||
func (c *HelloController) Patch() {}
|
||||
func (c *HelloController) Options() {}
|
||||
func (c *HelloController) Trace() {}
|
||||
func (c *ExampleController) Post() {}
|
||||
func (c *ExampleController) Put() {}
|
||||
func (c *ExampleController) Delete() {}
|
||||
func (c *ExampleController) Connect() {}
|
||||
func (c *ExampleController) Head() {}
|
||||
func (c *ExampleController) Patch() {}
|
||||
func (c *ExampleController) Options() {}
|
||||
func (c *ExampleController) Trace() {}
|
||||
*/
|
||||
|
||||
/*
|
||||
func (c *HelloController) All() {}
|
||||
func (c *ExampleController) All() {}
|
||||
// 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) {
|
||||
ctx.StopExecution()
|
||||
|
||||
httpStatus := http.StatusFound // a 'temporary-redirect-like' which works better than for our purpose
|
||||
if len(statusHeader) > 0 && statusHeader[0] > 0 {
|
||||
httpStatus = statusHeader[0]
|
||||
// get the previous status code given by the end-developer.
|
||||
status := ctx.GetStatusCode()
|
||||
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 == "" {
|
||||
method = tt.method
|
||||
}
|
||||
ex := e.Request(tt.method, req.path)
|
||||
ex := e.Request(method, req.path)
|
||||
if req.subdomain != "" {
|
||||
ex.WithURL("http://" + req.subdomain + ".localhost:8080")
|
||||
}
|
||||
|
|
28
doc.go
28
doc.go
|
@ -163,10 +163,10 @@ Example code:
|
|||
|
||||
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.
|
||||
|
||||
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
|
||||
|
@ -190,13 +190,22 @@ Below you'll read some usage examples:
|
|||
|
||||
|
||||
// Automatic TLS
|
||||
app.Run(iris.AutoTLS("localhost:443"))
|
||||
app.Run(iris.AutoTLS(":443", "example.com", "admin@example.com"))
|
||||
|
||||
|
||||
// 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 {
|
||||
panic(err)
|
||||
app.Logger().Fatal(err)
|
||||
}
|
||||
|
||||
if err = os.Chmod(socketFile, mode); err != nil {
|
||||
app.Logger().Fatal(err)
|
||||
}
|
||||
|
||||
app.Run(iris.Listener(l))
|
||||
|
@ -471,15 +480,12 @@ A group can have a nested group too.
|
|||
Example code:
|
||||
|
||||
|
||||
users:= app.Party("/users", myAuthHandler)
|
||||
users := app.Party("/users", myAuthMiddlewareHandler)
|
||||
|
||||
// http://myhost.com/users/42/profile
|
||||
users.Get("/{userid:int}/profile", userProfileHandler)
|
||||
users.Get("/{id:int}/profile", userProfileHandler)
|
||||
// http://myhost.com/users/messages/1
|
||||
users.Get("/inbox/{messageid:int}", userMessageHandler)
|
||||
|
||||
app.Run(iris.Addr("myhost.com:80"))
|
||||
|
||||
users.Get("/inbox/{id:int}", userMessageHandler)
|
||||
|
||||
|
||||
Custom HTTP Errors
|
||||
|
|
|
@ -63,17 +63,18 @@ import (
|
|||
// Look `core/router/APIBuilder#Controller` method too.
|
||||
type Controller struct {
|
||||
// Name contains the current controller's full name.
|
||||
//
|
||||
// doesn't change on different paths.
|
||||
Name string
|
||||
|
||||
// currentRoute is the current request context's route.
|
||||
currentRoute context.RouteReadOnly
|
||||
|
||||
// contains the `Name` as different words, all lowercase,
|
||||
// without the "Controller" suffix if exists.
|
||||
// we need this as field because the activator
|
||||
// we will not try to parse these if not needed
|
||||
// it's up to the end-developer to call `RelPath()` or `RelTmpl()`
|
||||
// which will result to fill them.
|
||||
//
|
||||
// doesn't change on different paths.
|
||||
nameAsWords []string
|
||||
|
||||
// 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 UserPostController and request path is "/user/post" then it's "/"
|
||||
// if UserProfile and request path is "/user/profile/likes" then it's "/likes"
|
||||
//
|
||||
// doesn't change on different paths.
|
||||
relPath string
|
||||
|
||||
// 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
|
||||
// Params are the request path's parameters, i.e
|
||||
// for route like "/user/{id}" and request to "/user/42"
|
||||
|
@ -101,13 +104,19 @@ type Controller struct {
|
|||
// If UserController then it's "user/"
|
||||
// if UserPostController then it's "user/post/"
|
||||
// if UserProfile then it's "user/profile/".
|
||||
//
|
||||
// doesn't change on different paths.
|
||||
relTmpl string
|
||||
|
||||
// view read and write,
|
||||
// can be already set-ed by previous handlers as well.
|
||||
Layout string
|
||||
Tmpl string
|
||||
Data map[string]interface{}
|
||||
|
||||
ContentType string
|
||||
Text string // or Text
|
||||
|
||||
// give access to the request context itself.
|
||||
Ctx context.Context
|
||||
}
|
||||
|
@ -127,10 +136,7 @@ func (c *Controller) getNameWords() []string {
|
|||
|
||||
// Route returns the current request controller's context read-only access route.
|
||||
func (c *Controller) Route() context.RouteReadOnly {
|
||||
if c.currentRoute == nil {
|
||||
c.currentRoute = c.Ctx.GetCurrentRoute()
|
||||
}
|
||||
return c.currentRoute
|
||||
return c.Ctx.GetCurrentRoute()
|
||||
}
|
||||
|
||||
const slashStr = "/"
|
||||
|
@ -208,6 +214,13 @@ func (c *Controller) RelTmpl() string {
|
|||
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
|
||||
// it initialize the Ctx and other fields.
|
||||
//
|
||||
|
@ -221,12 +234,26 @@ func (c *Controller) BeginRequest(ctx context.Context) {
|
|||
c.Status = ctx.GetStatusCode()
|
||||
// share 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)
|
||||
|
||||
// context itself
|
||||
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
|
||||
// before response sent.
|
||||
//
|
||||
|
@ -236,25 +263,32 @@ func (c *Controller) BeginRequest(ctx context.Context) {
|
|||
// It's called internally.
|
||||
// End-Developer can ovveride it but still should be called at the end.
|
||||
func (c *Controller) EndRequest(ctx context.Context) {
|
||||
if path := c.Path; path != "" && path != ctx.Path() {
|
||||
// then redirect
|
||||
ctx.Redirect(path)
|
||||
if ctx.ResponseWriter().Written() > 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if status := c.Status; status > 0 && status != ctx.GetStatusCode() {
|
||||
ctx.StatusCode(status)
|
||||
if path := c.Path; path != "" && path != ctx.Path() {
|
||||
// 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 layout := c.Layout; layout != "" {
|
||||
ctx.ViewLayout(layout)
|
||||
}
|
||||
if data := c.Data; data != nil {
|
||||
if data := c.Data; len(data) > 0 {
|
||||
for k, v := range data {
|
||||
ctx.ViewData(k, v)
|
||||
}
|
||||
}
|
||||
|
||||
ctx.View(view)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user