Nothing that you couldn't do before.


Former-commit-id: 658ec25d8045d25a76f87c8f992e67e64006e287
This commit is contained in:
Gerasimos (Makis) Maropoulos 2017-03-28 07:53:57 +03:00
parent 126c4de29b
commit 57576c70cb
7 changed files with 261 additions and 13 deletions

View File

@ -8,13 +8,21 @@
## 6.1.4 -> 6.2.0 (√Νεxτ) ## 6.1.4 -> 6.2.0 (√Νεxτ)
_Update: 28 March 2017_
- **View**: Provide an easier method on the community's question about "injecting" additional data outside of the route's main handler which calls the .Render, via middleware.
- As discussed [above](http://support.iris-go.com/d/27-using-middleware-to-inject-properties-for-templates).
- Click [here](https://github.com/kataras/iris/tree/v6/_examples/intermediate/view/context-view-data) for an example.
_Update: 18 March 2017_ _Update: 18 March 2017_
- **Sessions**: Enchance the community feature request about custom encode and decode methods for the cookie value(sessionid) as requested [here](http://support.iris-go.com/d/29-mark-cookie-for-session-as-secure). - **Sessions**: Enchance the community's feature request about custom encode and decode methods for the cookie value(sessionid) as requested [here](http://support.iris-go.com/d/29-mark-cookie-for-session-as-secure).
_Update: 12 March 2017_ _Update: 12 March 2017_
- Enhance Custom http errors with gzip and static files handler, as requested/reported [here](http://support.iris-go.com/d/17-fallback-handler-for-non-matched-routes/9). - Enhance Custom http errors with gzip and static files handler, as requested/reported [here](http://support.iris-go.com/d/17-fallback-handler-for-non-matched-routes).
- Enhance per-party custom http errors (now it works on any wildcard path too). - Enhance per-party custom http errors (now it works on any wildcard path too).
- Add a third parameter on `app.OnError(...)` for custom http errors with regexp validation, see [status_test.go](https://github.com/kataras/iris/blob/v6/status_test.go) for an example. - Add a third parameter on `app.OnError(...)` for custom http errors with regexp validation, see [status_test.go](https://github.com/kataras/iris/blob/v6/status_test.go) for an example.
- Add a `context.ParamIntWildcard(...)` to skip the first slash, useful for wildcarded paths' parameters. - Add a `context.ParamIntWildcard(...)` to skip the first slash, useful for wildcarded paths' parameters.

View File

@ -129,6 +129,76 @@ Feature Overview
- Feels like you used iris forever, thanks to its Fluent API - Feels like you used iris forever, thanks to its Fluent API
- And many others... - And many others...
Table of Contents
-----------
<img align="right" src="http://iris-go.com/assets/book/cover_4.jpg" width="300" />
* [Level: Beginner](_examples/beginner)
* [Hello World](_examples/beginner/hello-world/main.go)
* [Routes (using httprouter)](_examples/beginner/routes-using-httprouter/main.go)
* [Routes (using gorillamux)](_examples/beginner/routes-using-gorillamux/main.go)
* [Internal Application File Logger](_examples/beginner/file-logger/main.go)
* [Write JSON](_examples/beginner/write-json/main.go)
* [Read JSON](_examples/beginner/read-json/main.go)
* [Read Form](_examples/beginner/read-form/main.go)
* [Favicon](_examples/beginner/favicon/main.go)
* [File Server](_examples/beginner/file-server/main.go)
* [Send Files](_examples/beginner/send-files/main.go)
* [Stream Writer](_examples/beginner/stream-writer/main.go)
* [Listen UNIX Socket](_examples/beginner/listen-unix/main.go)
* [Listen TLS](_examples/beginner/listen-tls/main.go)
* [Listen Letsencrypt (Automatic Certifications)](_examples/beginner/listen-letsencrypt/main.go)
* [Level: Intermediate](_examples/intermediate)
* [Send An E-mail](_examples/intermediate/e-mail/main.go)
* [Upload/Read Files](_examples/intermediate/upload-files/main.go)
* [Request Logger](_examples/intermediate/request-logger/main.go)
* [Profiling (pprof)](_examples/intermediate/pprof/main.go)
* [Basic Authentication](_examples/intermediate/basicauth/main.go)
* [HTTP Access Control](_examples/intermediate/cors/main.go)
* [Cache Markdown](_examples/intermediate/cache-markdown/main.go)
* [Localization and Internationalization](_examples/intermediate/i18n/main.go)
* [Recovery](_examples/intermediate/recover/main.go)
* [Graceful Shutdown](_examples/intermediate/graceful-shutdown/main.go)
* [Custom TCP Listener](_examples/intermediate/custom-listener/main.go)
* [Custom HTTP Server](_examples/intermediate/custom-httpserver/main.go)
* [View Engine](_examples/intermediate/view)
* [Overview](_examples/intermediate/view/overview/main.go)
* [Template HTML: Part Zero](_examples/intermediate/view/template_html_0/main.go)
* [Template HTML: Part One](_examples/intermediate/view/template_html_1/main.go)
* [Template HTML: Part Two](_examples/intermediate/view/template_html_2/main.go)
* [Template HTML: Part Three](_examples/intermediate/view/template_html_3/main.go)
* [Template HTML: Part Four](_examples/intermediate/view/template_html_4/main.go)
* [Inject Data Between Handlers](_examples/intermediate/view/context-view-data/main.go)
* [Embedding Templates Into Executable](_examples/intermediate/embedding-templates-into-app)
* [Custom Renderer](_examples/intermediate/view/custom-renderer/main.go)
* [Password Hashing](_examples/intermediate/password-hashing/main.go)
* [Sessions](_examples/intermediate/sessions)
* [Overview](_examples/intermediate/sessions/overview/main.go)
* [Encoding & Decoding the Session ID: Secure Cookie](_examples/intermediate/sessions/securecookie/main.go)
* [Standalone](_examples/intermediate/sessions/standalone/main.go)
* [With A Back-End Database](_examples/intermediate/sessions/database/main.go)
* [Flash Messages](_examples/intermediate/flash-messages/main.go)
* [Websockets](_examples/intermediate/websockets)
* [Ridiculous Simple](_examples/intermediate/websockets/ridiculous-simple/main.go)
* [Overview](_examples/intermediate/websockets/overview/main.go)
* [Connection List](_examples/intermediate/websockets/connectionlist/main.go)
* [Native Messages](_examples/intermediate/websockets/naive-messages/main.go)
* [Secure](_examples/intermediate/websockets/secure/main.go)
* [Custom Go Client](_examples/intermediate/websockets/custom-go-client/main.go)
* [Level: Advanced](_examples/advanced)
* [Transactions](_examples/advanced/transactions/main.go)
* [HTTP Testing](_examples/advanced/httptest/main_test.go)
* [Watch & Compile Typescript source files](_examples/advanced/typescript/main.go)
* [Cloud Editor](_examples/advanced/cloud-editor/main.go)
* [Online Visitors](_examples/advanced/online-visitors/main.go)
* [URL Shortener using BoltDB](_examples/advanced/url-shortener/main.go)
* [Subdomains](_examples/advanced/subdomains)
* [Single](_examples/advanced/subdomains/single/main.go)
* [Multi](_examples/advanced/subdomains/multi/main.go)
* [Wildcard](_examples/advanced/subdomains/wildcard/main.go)
Installation Installation
----------- -----------

View File

@ -38,12 +38,13 @@ It doesn't contains "best ways" neither explains all its features. It's just a s
* [Custom HTTP Server](intermediate/custom-httpserver/main.go) * [Custom HTTP Server](intermediate/custom-httpserver/main.go)
* [View Engine](intermediate/view) * [View Engine](intermediate/view)
* [Overview](intermediate/view/overview/main.go) * [Overview](intermediate/view/overview/main.go)
* [Embedding Templates Into Executable](intermediate/embedding-templates-into-app)
* [Template HTML: Part Zero](intermediate/view/template_html_0/main.go) * [Template HTML: Part Zero](intermediate/view/template_html_0/main.go)
* [Template HTML: Part One](intermediate/view/template_html_1/main.go) * [Template HTML: Part One](intermediate/view/template_html_1/main.go)
* [Template HTML: Part Two](intermediate/view/template_html_2/main.go) * [Template HTML: Part Two](intermediate/view/template_html_2/main.go)
* [Template HTML: Part Three](intermediate/view/template_html_3/main.go) * [Template HTML: Part Three](intermediate/view/template_html_3/main.go)
* [Template HTML: Part Four](intermediate/view/template_html_4/main.go) * [Template HTML: Part Four](intermediate/view/template_html_4/main.go)
* [Inject Data Between Handlers](intermediate/view/context-view-data/main.go)
* [Embedding Templates Into Executable](intermediate/embedding-templates-into-app)
* [Custom Renderer](intermediate/view/custom-renderer/main.go) * [Custom Renderer](intermediate/view/custom-renderer/main.go)
* [Password Hashing](intermediate/password-hashing/main.go) * [Password Hashing](intermediate/password-hashing/main.go)
* [Sessions](intermediate/sessions) * [Sessions](intermediate/sessions)

View File

@ -0,0 +1,58 @@
// this example will show you how you can set per-request data for a template outside of the main handler which calls
// the .Render, via middleware.
//
// Remember: .Render has the "binding" argument which can be used to send data to the template at any case.
package main
import (
"time"
"gopkg.in/kataras/iris.v6"
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
"gopkg.in/kataras/iris.v6/adaptors/view"
)
const (
DefaultTitle = "My Awesome Site"
DefaultLayout = "layouts/layout.html"
)
func main() {
app := iris.New()
// output startup banner and error logs on os.Stdout
app.Adapt(iris.DevLogger())
// set the router, you can choose gorillamux too
app.Adapt(httprouter.New())
// set the view engine target to ./templates folder
app.Adapt(view.HTML("./templates", ".html").Reload(true))
app.UseFunc(func(ctx *iris.Context) {
// set the title, current time and a layout in order to be used if and when the next handler(s) calls the .Render function
ctx.ViewData("Title", DefaultTitle)
now := time.Now().Format(app.Config.TimeFormat)
ctx.ViewData("CurrentTime", now)
ctx.ViewLayout(DefaultLayout)
ctx.Next()
})
app.Get("/", func(ctx *iris.Context) {
ctx.ViewData("BodyMessage", "a sample text here... setted by the route handler")
if err := ctx.Render("index.html", nil); err != nil {
app.Log(iris.DevMode, err.Error())
}
})
app.Get("/about", func(ctx *iris.Context) {
ctx.ViewData("Title", "My About Page")
ctx.ViewData("BodyMessage", "about text here... setted by the route handler")
// same file, just to keep things simple.
if err := ctx.Render("index.html", nil); err != nil {
app.Log(iris.DevMode, err.Error())
}
})
// Open localhost:8080 and localhost:8080/about
app.Listen(":8080")
}

View File

@ -0,0 +1,8 @@
<h1>
Title: {{.Title}}
</h1>
<h3>{{.BodyMessage}} </h3>
<hr/>
Current time: {{.CurrentTime}}

View File

@ -0,0 +1,10 @@
<html>
<head>
<title>My WebsiteLayout</title>
</head>
<body>
<!-- Render the current template here -->
{{ yield }}
</body>
</html>

View File

@ -869,13 +869,6 @@ func (ctx *Context) TryWriteGzip(b []byte) (int, error) {
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
const (
// NoLayout to disable layout for a particular template file
NoLayout = "@.|.@no_layout@.|.@"
// TemplateLayoutContextKey is the name of the user values which can be used to set a template layout from a middleware and override the parent's
TemplateLayoutContextKey = "templateLayout"
)
// getGzipOption receives a default value and the render options map and returns if gzip is enabled for this render action // getGzipOption receives a default value and the render options map and returns if gzip is enabled for this render action
func getGzipOption(defaultValue bool, options map[string]interface{}) bool { func getGzipOption(defaultValue bool, options map[string]interface{}) bool {
gzipOpt := options["gzip"] // we only need that, so don't create new map to keep the options. gzipOpt := options["gzip"] // we only need that, so don't create new map to keep the options.
@ -933,8 +926,66 @@ func (ctx *Context) fastRenderWithStatus(status int, cType string, data []byte)
return return
} }
const (
// NoLayout to disable layout for a particular template file
NoLayout = "@.|.@no_layout@.|.@"
// ViewLayoutContextKey is the name of the user values which can be used to set a template layout from a middleware and override the parent's
ViewLayoutContextKey = "@viewLayout"
ViewDataContextKey = "@viewData"
// conversions
// TemplateLayoutContextKey same as ViewLayoutContextKey
TemplateLayoutContextKey = ViewLayoutContextKey
)
// ViewLayout sets the "layout" option if and when .Render
// is being called afterwards, in the same request.
// Useful when need to set or/and change a layout based on the previous handlers in the chain.
//
// Look: .ViewData | .Render
// .MustRender | .RenderWithStatus also.
//
// Example: https://github.com/kataras/iris/tree/v6/_examples/intermediate/view/context-view-data/
func (ctx *Context) ViewLayout(layoutTmplFile string) {
ctx.Set(ViewLayoutContextKey, layoutTmplFile)
}
// ViewData saves one or more key-value pair in order to be passed if and when .Render
// is being called afterwards, in the same request.
// Useful when need to set or/and change template data from previous hanadlers in the chain.
//
// If .Render's "binding" argument is not nil and it's not a type of map
// then these data are being ignored, binding has the priority, so the main route's handler can still decide.
// If binding is a map or iris.Map then theese data are being added to the view data
// and passed to the template.
//
// After .Render, the data are not destroyed, in order to be re-used if needed (again, in the same request as everything else),
// to manually clear the view data, developers can call:
// ctx.Set(iris.ViewDataContextKey, iris.Map{})
//
// Look: .ViewLayout | .Render
// .MustRender | .RenderWithStatus also.
//
// Example: https://github.com/kataras/iris/tree/v6/_examples/intermediate/view/context-view-data/
func (ctx *Context) ViewData(key string, value interface{}) {
v := ctx.Get(ViewDataContextKey)
if v == nil {
ctx.Set(ViewDataContextKey, Map{key: value})
return
}
if data, ok := v.(Map); ok {
data[key] = value
}
}
// RenderWithStatus builds up the response from the specified template or a serialize engine. // RenderWithStatus builds up the response from the specified template or a serialize engine.
// Note: the options: "gzip" and "charset" are built'n support by Iris, so you can pass these on any template engine or serialize engines // Note: the options: "gzip" and "charset" are built'n support by Iris, so you can pass these on any template engine or serialize engines.
//
// Look: .ViewData | .Render
// .ViewLayout | .MustRender also.
//
// Examples: https://github.com/kataras/iris/tree/v6/_examples/intermediate/view/
func (ctx *Context) RenderWithStatus(status int, name string, binding interface{}, options ...map[string]interface{}) (err error) { func (ctx *Context) RenderWithStatus(status int, name string, binding interface{}, options ...map[string]interface{}) (err error) {
if _, shouldFirstStatusCode := ctx.ResponseWriter.(*responseWriter); shouldFirstStatusCode { if _, shouldFirstStatusCode := ctx.ResponseWriter.(*responseWriter); shouldFirstStatusCode {
ctx.SetStatusCode(status) ctx.SetStatusCode(status)
@ -957,6 +1008,38 @@ func (ctx *Context) RenderWithStatus(status int, name string, binding interface{
} }
} }
// optional, view data (useful for middleware, although user can already do that with ctx.Set/Get)
// check if user sets any view data
if v := ctx.Get(ViewDataContextKey); v != nil {
// if so, then check its type, to make sure
if data, ok := ctx.Get(ViewDataContextKey).(Map); ok {
if len(data) > 0 {
if binding != nil {
// if binding is passed to the Render function then
// two things can happen:
// if binding is a custom type, we ignore the data
// if binding is a map of interface{} or string then, add these to the view data
// finally, set the binding to the new data and pass it to the view engine, as we did before.
if irisMap, ok := binding.(Map); ok {
for key, val := range irisMap {
data[key] = val
} // a little of necessary duplication here...
} else if stdMap, ok := binding.(map[string]interface{}); ok {
for key, val := range stdMap {
data[key] = val
}
} else if stdMapStr, ok := binding.(map[string]string); ok {
for key, val := range stdMapStr {
data[key] = val
}
}
}
binding = data
}
}
}
// Find Content type // Find Content type
// if it the name is not a template file, then take that as the content type. // if it the name is not a template file, then take that as the content type.
cType := contentHTML cType := contentHTML
@ -999,7 +1082,12 @@ func (ctx *Context) RenderWithStatus(status int, name string, binding interface{
// Render same as .RenderWithStatus but with status to iris.StatusOK (200) if no previous status exists // Render same as .RenderWithStatus but with status to iris.StatusOK (200) if no previous status exists
// builds up the response from the specified template or a serialize engine. // builds up the response from the specified template or a serialize engine.
// Note: the options: "gzip" and "charset" are built'n support by Iris, so you can pass these on any template engine or serialize engine // Note: the options: "gzip" and "charset" are built'n support by Iris, so you can pass these on any template engine or serialize engine.
//
// Look: .ViewData | .MustRender
// .ViewLayout | .RenderWithStatus also.
//
// Examples: https://github.com/kataras/iris/tree/v6/_examples/intermediate/view/
func (ctx *Context) Render(name string, binding interface{}, options ...map[string]interface{}) error { func (ctx *Context) Render(name string, binding interface{}, options ...map[string]interface{}) error {
errCode := ctx.ResponseWriter.StatusCode() errCode := ctx.ResponseWriter.StatusCode()
if errCode <= 0 { if errCode <= 0 {
@ -1009,7 +1097,12 @@ func (ctx *Context) Render(name string, binding interface{}, options ...map[stri
} }
// MustRender same as .Render but returns 503 service unavailable http status with a (html) message if render failed // MustRender same as .Render but returns 503 service unavailable http status with a (html) message if render failed
// Note: the options: "gzip" and "charset" are built'n support by Iris, so you can pass these on any template engine or serialize engine // Note: the options: "gzip" and "charset" are built'n support by Iris, so you can pass these on any template engine or serialize engine.
//
// Look: .ViewData | .Render
// .ViewLayout | .RenderWithStatus also.
//
// Examples: https://github.com/kataras/iris/tree/v6/_examples/intermediate/view/
func (ctx *Context) MustRender(name string, binding interface{}, options ...map[string]interface{}) { func (ctx *Context) MustRender(name string, binding interface{}, options ...map[string]interface{}) {
if err := ctx.Render(name, binding, options...); err != nil { if err := ctx.Render(name, binding, options...); err != nil {
htmlErr := ctx.HTML(StatusServiceUnavailable, htmlErr := ctx.HTML(StatusServiceUnavailable,