mirror of
https://github.com/kataras/iris.git
synced 2025-03-14 08:16:28 +01:00
add quicktemplate example. Iris + Quicktemplate made easy 👍
Former-commit-id: b17fb21d8c1d5a73f9f9170f49ae0527870377a1
This commit is contained in:
parent
093d087a68
commit
feb1d264c0
|
@ -121,6 +121,9 @@ Navigate through examples for a better understanding.
|
||||||
- [Inject Data Between Handlers](view/context-view-data/main.go)
|
- [Inject Data Between Handlers](view/context-view-data/main.go)
|
||||||
- [Embedding Templates Into App Executable File](view/embedding-templates-into-app/main.go)
|
- [Embedding Templates Into App Executable File](view/embedding-templates-into-app/main.go)
|
||||||
|
|
||||||
|
|
||||||
|
You can serve [quicktemplate](https://github.com/valyala/quicktemplate) files too, simply by using the `context#ResponseWriter`, take a look at the [http_responsewriter/quicktemplate](http_responsewriter/quicktemplate) example.
|
||||||
|
|
||||||
### Authentication
|
### Authentication
|
||||||
|
|
||||||
- [Basic Authentication](authentication/basicauth/main.go)
|
- [Basic Authentication](authentication/basicauth/main.go)
|
||||||
|
@ -148,6 +151,7 @@ Navigate through examples for a better understanding.
|
||||||
|
|
||||||
### How to Write to `context.ResponseWriter() http.ResponseWriter`
|
### How to Write to `context.ResponseWriter() http.ResponseWriter`
|
||||||
|
|
||||||
|
- [Write `valyala/quicktemplate` templates](http_responsewriter/quicktemplate)
|
||||||
- [Text, Markdown, HTML, JSON, JSONP, XML, Binary](http_responsewriter/write-rest/main.go)
|
- [Text, Markdown, HTML, JSON, JSONP, XML, Binary](http_responsewriter/write-rest/main.go)
|
||||||
- [Stream Writer](http_responsewriter/stream-writer/main.go)
|
- [Stream Writer](http_responsewriter/stream-writer/main.go)
|
||||||
- [Transactions](http_responsewriter/transactions/main.go)
|
- [Transactions](http_responsewriter/transactions/main.go)
|
||||||
|
|
19
_examples/http_responsewriter/quicktemplate/README.md
Normal file
19
_examples/http_responsewriter/quicktemplate/README.md
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
First of all, install [quicktemplate](https://github.com/valyala/quicktemplate) package and [quicktemplate compiler](https://github.com/valyala/quicktemplate/tree/master/qtc)
|
||||||
|
|
||||||
|
```sh
|
||||||
|
go get -u github.com/valyala/quicktemplate
|
||||||
|
go get -u github.com/valyala/quicktemplate/qtc
|
||||||
|
```
|
||||||
|
|
||||||
|
The example has the Go code compiled already for you, therefore:
|
||||||
|
```sh
|
||||||
|
go run main.go # http://localhost:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
However there is an instruction below, full documentation can be found at https://github.com/valyala/quicktemplate.
|
||||||
|
|
||||||
|
Save your template files into `templates` folder under the extension *.qtpl, open your terminal and run `qtc` inside this folder.
|
||||||
|
|
||||||
|
If all went ok, `*.qtpl.go` files must appear in the `templates` folder. These files contain the Go code for all `*.qtpl` files.
|
||||||
|
|
||||||
|
> Remember, each time you change a a `/templates/*.qtpl` file you have to run the `qtc` command and re-build your application.
|
|
@ -0,0 +1,14 @@
|
||||||
|
package controllers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/kataras/iris/_examples/http_responsewriter/quicktemplate/templates"
|
||||||
|
|
||||||
|
"github.com/kataras/iris/context"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ExecuteTemplate renders a "tmpl" partial template to the `context#ResponseWriter`.
|
||||||
|
func ExecuteTemplate(ctx context.Context, tmpl templates.Partial) {
|
||||||
|
ctx.Gzip(true)
|
||||||
|
ctx.ContentType("text/html")
|
||||||
|
templates.WriteTemplate(ctx.ResponseWriter(), tmpl)
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package controllers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/kataras/iris/_examples/http_responsewriter/quicktemplate/templates"
|
||||||
|
|
||||||
|
"github.com/kataras/iris/context"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Hello renders our ../templates/hello.qtpl file using the compiled ../templates/hello.qtpl.go file.
|
||||||
|
func Hello(ctx context.Context) {
|
||||||
|
// vars := make(map[string]interface{})
|
||||||
|
// vars["message"] = "Hello World!"
|
||||||
|
// vars["name"] = ctx.Params().Get("name")
|
||||||
|
// [...]
|
||||||
|
// &templates.Hello{ Vars: vars }
|
||||||
|
// [...]
|
||||||
|
|
||||||
|
// However, as an alternative, we recommend that you should the `ctx.ViewData(key, value)`
|
||||||
|
// in order to be able modify the `templates.Hello#Vars` from a middleware(other handlers) as well.
|
||||||
|
ctx.ViewData("message", "Hello World!")
|
||||||
|
ctx.ViewData("name", ctx.Params().Get("name"))
|
||||||
|
|
||||||
|
// set view data to the `Vars` template's field
|
||||||
|
tmpl := &templates.Hello{
|
||||||
|
Vars: ctx.GetViewData(),
|
||||||
|
}
|
||||||
|
|
||||||
|
// render the template
|
||||||
|
ExecuteTemplate(ctx, tmpl)
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package controllers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/kataras/iris/_examples/http_responsewriter/quicktemplate/templates"
|
||||||
|
|
||||||
|
"github.com/kataras/iris/context"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Index renders our ../templates/index.qtpl file using the compiled ../templates/index.qtpl.go file.
|
||||||
|
func Index(ctx context.Context) {
|
||||||
|
tmpl := &templates.Index{}
|
||||||
|
|
||||||
|
// render the template
|
||||||
|
ExecuteTemplate(ctx, tmpl)
|
||||||
|
}
|
22
_examples/http_responsewriter/quicktemplate/main.go
Normal file
22
_examples/http_responsewriter/quicktemplate/main.go
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/kataras/iris/_examples/http_responsewriter/quicktemplate/controllers"
|
||||||
|
|
||||||
|
"github.com/kataras/iris"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newApp() *iris.Application {
|
||||||
|
app := iris.New()
|
||||||
|
app.Get("/", controllers.Index)
|
||||||
|
app.Get("/{name}", controllers.Hello)
|
||||||
|
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := newApp()
|
||||||
|
// http://localhost:8080
|
||||||
|
// http://localhost:8080/yourname
|
||||||
|
app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed))
|
||||||
|
}
|
47
_examples/http_responsewriter/quicktemplate/main_test.go
Normal file
47
_examples/http_responsewriter/quicktemplate/main_test.go
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/kataras/iris/httptest"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestResponseWriterQuicktemplate(t *testing.T) {
|
||||||
|
baseRawBody := `
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Quicktemplate integration with Iris</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
Header contents here...
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin:10px;">
|
||||||
|
|
||||||
|
<h1>%s</h1>
|
||||||
|
<div>
|
||||||
|
%s
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
<footer>
|
||||||
|
Footer contents here...
|
||||||
|
</footer>
|
||||||
|
</html>
|
||||||
|
`
|
||||||
|
|
||||||
|
expectedIndexRawBody := fmt.Sprintf(baseRawBody, "Index Page", "This is our index page's body.")
|
||||||
|
name := "yourname"
|
||||||
|
expectedHelloRawBody := fmt.Sprintf(baseRawBody, "Hello World!", "Hello <b>"+name+"!</b>")
|
||||||
|
|
||||||
|
app := newApp()
|
||||||
|
|
||||||
|
e := httptest.New(t, app)
|
||||||
|
|
||||||
|
e.GET("/").Expect().Status(httptest.StatusOK).Body().Equal(expectedIndexRawBody)
|
||||||
|
e.GET("/" + name).Expect().Status(httptest.StatusOK).Body().Equal(expectedHelloRawBody)
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
This is our templates' base implementation.
|
||||||
|
|
||||||
|
{% interface
|
||||||
|
Partial {
|
||||||
|
Body()
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
|
||||||
|
Template writes a template implementing the Partial interface.
|
||||||
|
{% func Template(p Partial) %}
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Quicktemplate integration with Iris</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
Header contents here...
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin:10px;">
|
||||||
|
{%= p.Body() %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
<footer>
|
||||||
|
Footer contents here...
|
||||||
|
</footer>
|
||||||
|
</html>
|
||||||
|
{% endfunc %}
|
||||||
|
|
||||||
|
|
||||||
|
Base template implementation. Other pages may inherit from it if they need
|
||||||
|
overriding only certain Partial methods.
|
||||||
|
{% code type Base struct {} %}
|
||||||
|
{% func (b *Base) Body() %}This is the base body{% endfunc %}
|
|
@ -0,0 +1,128 @@
|
||||||
|
// This file is automatically generated by qtc from "base.qtpl".
|
||||||
|
// See https://github.com/valyala/quicktemplate for details.
|
||||||
|
|
||||||
|
// This is our templates' base implementation.
|
||||||
|
//
|
||||||
|
|
||||||
|
//line base.qtpl:3
|
||||||
|
package templates
|
||||||
|
|
||||||
|
//line base.qtpl:3
|
||||||
|
import (
|
||||||
|
qtio422016 "io"
|
||||||
|
|
||||||
|
qt422016 "github.com/valyala/quicktemplate"
|
||||||
|
)
|
||||||
|
|
||||||
|
//line base.qtpl:3
|
||||||
|
var (
|
||||||
|
_ = qtio422016.Copy
|
||||||
|
_ = qt422016.AcquireByteBuffer
|
||||||
|
)
|
||||||
|
|
||||||
|
//line base.qtpl:4
|
||||||
|
type Partial interface {
|
||||||
|
//line base.qtpl:4
|
||||||
|
Body() string
|
||||||
|
//line base.qtpl:4
|
||||||
|
StreamBody(qw422016 *qt422016.Writer)
|
||||||
|
//line base.qtpl:4
|
||||||
|
WriteBody(qq422016 qtio422016.Writer)
|
||||||
|
//line base.qtpl:4
|
||||||
|
}
|
||||||
|
|
||||||
|
// Template writes a template implementing the Partial interface.
|
||||||
|
|
||||||
|
//line base.qtpl:11
|
||||||
|
func StreamTemplate(qw422016 *qt422016.Writer, p Partial) {
|
||||||
|
//line base.qtpl:11
|
||||||
|
qw422016.N().S(`
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Quicktemplate integration with Iris</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
Header contents here...
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin:10px;">
|
||||||
|
`)
|
||||||
|
//line base.qtpl:22
|
||||||
|
p.StreamBody(qw422016)
|
||||||
|
//line base.qtpl:22
|
||||||
|
qw422016.N().S(`
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
<footer>
|
||||||
|
Footer contents here...
|
||||||
|
</footer>
|
||||||
|
</html>
|
||||||
|
`)
|
||||||
|
//line base.qtpl:30
|
||||||
|
}
|
||||||
|
|
||||||
|
//line base.qtpl:30
|
||||||
|
func WriteTemplate(qq422016 qtio422016.Writer, p Partial) {
|
||||||
|
//line base.qtpl:30
|
||||||
|
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||||
|
//line base.qtpl:30
|
||||||
|
StreamTemplate(qw422016, p)
|
||||||
|
//line base.qtpl:30
|
||||||
|
qt422016.ReleaseWriter(qw422016)
|
||||||
|
//line base.qtpl:30
|
||||||
|
}
|
||||||
|
|
||||||
|
//line base.qtpl:30
|
||||||
|
func Template(p Partial) string {
|
||||||
|
//line base.qtpl:30
|
||||||
|
qb422016 := qt422016.AcquireByteBuffer()
|
||||||
|
//line base.qtpl:30
|
||||||
|
WriteTemplate(qb422016, p)
|
||||||
|
//line base.qtpl:30
|
||||||
|
qs422016 := string(qb422016.B)
|
||||||
|
//line base.qtpl:30
|
||||||
|
qt422016.ReleaseByteBuffer(qb422016)
|
||||||
|
//line base.qtpl:30
|
||||||
|
return qs422016
|
||||||
|
//line base.qtpl:30
|
||||||
|
}
|
||||||
|
|
||||||
|
// Base template implementation. Other pages may inherit from it if they need
|
||||||
|
// overriding only certain Partial methods.
|
||||||
|
|
||||||
|
//line base.qtpl:35
|
||||||
|
type Base struct{}
|
||||||
|
|
||||||
|
//line base.qtpl:36
|
||||||
|
func (b *Base) StreamBody(qw422016 *qt422016.Writer) {
|
||||||
|
//line base.qtpl:36
|
||||||
|
qw422016.N().S(`This is the base body`) }
|
||||||
|
|
||||||
|
//line base.qtpl:36
|
||||||
|
//line base.qtpl:36
|
||||||
|
func (b *Base) WriteBody(qq422016 qtio422016.Writer) {
|
||||||
|
//line base.qtpl:36
|
||||||
|
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||||
|
//line base.qtpl:36
|
||||||
|
b.StreamBody(qw422016)
|
||||||
|
//line base.qtpl:36
|
||||||
|
qt422016.ReleaseWriter(qw422016)
|
||||||
|
//line base.qtpl:36
|
||||||
|
}
|
||||||
|
|
||||||
|
//line base.qtpl:36
|
||||||
|
func (b *Base) Body() string {
|
||||||
|
//line base.qtpl:36
|
||||||
|
qb422016 := qt422016.AcquireByteBuffer()
|
||||||
|
//line base.qtpl:36
|
||||||
|
b.WriteBody(qb422016)
|
||||||
|
//line base.qtpl:36
|
||||||
|
qs422016 := string(qb422016.B)
|
||||||
|
//line base.qtpl:36
|
||||||
|
qt422016.ReleaseByteBuffer(qb422016)
|
||||||
|
//line base.qtpl:36
|
||||||
|
return qs422016
|
||||||
|
//line base.qtpl:36
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
Hello template, implements the Partial's methods.
|
||||||
|
|
||||||
|
{% code
|
||||||
|
type Hello struct {
|
||||||
|
Vars map[string]interface{}
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
{% func (h *Hello) Body() %}
|
||||||
|
<h1>{%v h.Vars["message"] %}</h1>
|
||||||
|
<div>
|
||||||
|
Hello <b>{%v h.Vars["name"] %}!</b>
|
||||||
|
</div>
|
||||||
|
{% endfunc %}
|
|
@ -0,0 +1,72 @@
|
||||||
|
// This file is automatically generated by qtc from "hello.qtpl".
|
||||||
|
// See https://github.com/valyala/quicktemplate for details.
|
||||||
|
|
||||||
|
// Hello template, implements the Partial's methods.
|
||||||
|
//
|
||||||
|
|
||||||
|
//line hello.qtpl:3
|
||||||
|
package templates
|
||||||
|
|
||||||
|
//line hello.qtpl:3
|
||||||
|
import (
|
||||||
|
qtio422016 "io"
|
||||||
|
|
||||||
|
qt422016 "github.com/valyala/quicktemplate"
|
||||||
|
)
|
||||||
|
|
||||||
|
//line hello.qtpl:3
|
||||||
|
var (
|
||||||
|
_ = qtio422016.Copy
|
||||||
|
_ = qt422016.AcquireByteBuffer
|
||||||
|
)
|
||||||
|
|
||||||
|
//line hello.qtpl:4
|
||||||
|
type Hello struct {
|
||||||
|
Vars map[string]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
//line hello.qtpl:9
|
||||||
|
func (h *Hello) StreamBody(qw422016 *qt422016.Writer) {
|
||||||
|
//line hello.qtpl:9
|
||||||
|
qw422016.N().S(`
|
||||||
|
<h1>`)
|
||||||
|
//line hello.qtpl:10
|
||||||
|
qw422016.E().V(h.Vars["message"])
|
||||||
|
//line hello.qtpl:10
|
||||||
|
qw422016.N().S(`</h1>
|
||||||
|
<div>
|
||||||
|
Hello <b>`)
|
||||||
|
//line hello.qtpl:12
|
||||||
|
qw422016.E().V(h.Vars["name"])
|
||||||
|
//line hello.qtpl:12
|
||||||
|
qw422016.N().S(`!</b>
|
||||||
|
</div>
|
||||||
|
`)
|
||||||
|
//line hello.qtpl:14
|
||||||
|
}
|
||||||
|
|
||||||
|
//line hello.qtpl:14
|
||||||
|
func (h *Hello) WriteBody(qq422016 qtio422016.Writer) {
|
||||||
|
//line hello.qtpl:14
|
||||||
|
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||||
|
//line hello.qtpl:14
|
||||||
|
h.StreamBody(qw422016)
|
||||||
|
//line hello.qtpl:14
|
||||||
|
qt422016.ReleaseWriter(qw422016)
|
||||||
|
//line hello.qtpl:14
|
||||||
|
}
|
||||||
|
|
||||||
|
//line hello.qtpl:14
|
||||||
|
func (h *Hello) Body() string {
|
||||||
|
//line hello.qtpl:14
|
||||||
|
qb422016 := qt422016.AcquireByteBuffer()
|
||||||
|
//line hello.qtpl:14
|
||||||
|
h.WriteBody(qb422016)
|
||||||
|
//line hello.qtpl:14
|
||||||
|
qs422016 := string(qb422016.B)
|
||||||
|
//line hello.qtpl:14
|
||||||
|
qt422016.ReleaseByteBuffer(qb422016)
|
||||||
|
//line hello.qtpl:14
|
||||||
|
return qs422016
|
||||||
|
//line hello.qtpl:14
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
Index template, implements the Partial's methods.
|
||||||
|
|
||||||
|
{% code
|
||||||
|
type Index struct {}
|
||||||
|
%}
|
||||||
|
|
||||||
|
{% func (i *Index) Body() %}
|
||||||
|
<h1>Index Page</h1>
|
||||||
|
<div>
|
||||||
|
This is our index page's body.
|
||||||
|
</div>
|
||||||
|
{% endfunc %}
|
|
@ -0,0 +1,62 @@
|
||||||
|
// This file is automatically generated by qtc from "index.qtpl".
|
||||||
|
// See https://github.com/valyala/quicktemplate for details.
|
||||||
|
|
||||||
|
// Index template, implements the Partial's methods.
|
||||||
|
//
|
||||||
|
|
||||||
|
//line index.qtpl:3
|
||||||
|
package templates
|
||||||
|
|
||||||
|
//line index.qtpl:3
|
||||||
|
import (
|
||||||
|
qtio422016 "io"
|
||||||
|
|
||||||
|
qt422016 "github.com/valyala/quicktemplate"
|
||||||
|
)
|
||||||
|
|
||||||
|
//line index.qtpl:3
|
||||||
|
var (
|
||||||
|
_ = qtio422016.Copy
|
||||||
|
_ = qt422016.AcquireByteBuffer
|
||||||
|
)
|
||||||
|
|
||||||
|
//line index.qtpl:4
|
||||||
|
type Index struct{}
|
||||||
|
|
||||||
|
//line index.qtpl:7
|
||||||
|
func (i *Index) StreamBody(qw422016 *qt422016.Writer) {
|
||||||
|
//line index.qtpl:7
|
||||||
|
qw422016.N().S(`
|
||||||
|
<h1>Index Page</h1>
|
||||||
|
<div>
|
||||||
|
This is our index page's body.
|
||||||
|
</div>
|
||||||
|
`)
|
||||||
|
//line index.qtpl:12
|
||||||
|
}
|
||||||
|
|
||||||
|
//line index.qtpl:12
|
||||||
|
func (i *Index) WriteBody(qq422016 qtio422016.Writer) {
|
||||||
|
//line index.qtpl:12
|
||||||
|
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||||
|
//line index.qtpl:12
|
||||||
|
i.StreamBody(qw422016)
|
||||||
|
//line index.qtpl:12
|
||||||
|
qt422016.ReleaseWriter(qw422016)
|
||||||
|
//line index.qtpl:12
|
||||||
|
}
|
||||||
|
|
||||||
|
//line index.qtpl:12
|
||||||
|
func (i *Index) Body() string {
|
||||||
|
//line index.qtpl:12
|
||||||
|
qb422016 := qt422016.AcquireByteBuffer()
|
||||||
|
//line index.qtpl:12
|
||||||
|
i.WriteBody(qb422016)
|
||||||
|
//line index.qtpl:12
|
||||||
|
qs422016 := string(qb422016.B)
|
||||||
|
//line index.qtpl:12
|
||||||
|
qt422016.ReleaseByteBuffer(qb422016)
|
||||||
|
//line index.qtpl:12
|
||||||
|
return qs422016
|
||||||
|
//line index.qtpl:12
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/fatih/structs"
|
||||||
"github.com/microcosm-cc/bluemonday"
|
"github.com/microcosm-cc/bluemonday"
|
||||||
"github.com/monoculum/formam"
|
"github.com/monoculum/formam"
|
||||||
"github.com/russross/blackfriday"
|
"github.com/russross/blackfriday"
|
||||||
|
@ -486,6 +487,17 @@ type Context interface {
|
||||||
// Example: https://github.com/kataras/iris/tree/master/_examples/view/context-view-data/
|
// Example: https://github.com/kataras/iris/tree/master/_examples/view/context-view-data/
|
||||||
ViewData(key string, value interface{})
|
ViewData(key string, value interface{})
|
||||||
|
|
||||||
|
// GetViewData returns the values registered by `context#ViewData`.
|
||||||
|
// The return value is `map[string]interface{}`, this means that
|
||||||
|
// if a custom struct registered to ViewData then this function
|
||||||
|
// will try to parse it to map, if failed then the return value is nil
|
||||||
|
// A check for nil is always a good practise if different
|
||||||
|
// kind of values or no data are registered via `ViewData`.
|
||||||
|
//
|
||||||
|
// Similarly to `viewData := ctx.Values().Get("iris.viewData")` or
|
||||||
|
// `viewData := ctx.Values().Get(ctx.Application().ConfigurationReadOnly().GetViewDataContextKey())`.
|
||||||
|
GetViewData() map[string]interface{}
|
||||||
|
|
||||||
// View renders templates based on the adapted view engines.
|
// View renders templates based on the adapted view engines.
|
||||||
// First argument accepts the filename, relative to the view engine's Directory,
|
// First argument accepts the filename, relative to the view engine's Directory,
|
||||||
// i.e: if directory is "./templates" and want to render the "./templates/users/index.html"
|
// i.e: if directory is "./templates" and want to render the "./templates/users/index.html"
|
||||||
|
@ -1626,6 +1638,43 @@ func (ctx *context) ViewData(key string, value interface{}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetViewData returns the values registered by `context#ViewData`.
|
||||||
|
// The return value is `map[string]interface{}`, this means that
|
||||||
|
// if a custom struct registered to ViewData then this function
|
||||||
|
// will try to parse it to map, if failed then the return value is nil
|
||||||
|
// A check for nil is always a good practise if different
|
||||||
|
// kind of values or no data are registered via `ViewData`.
|
||||||
|
//
|
||||||
|
// Similarly to `viewData := ctx.Values().Get("iris.viewData")` or
|
||||||
|
// `viewData := ctx.Values().Get(ctx.Application().ConfigurationReadOnly().GetViewDataContextKey())`.
|
||||||
|
func (ctx *context) GetViewData() map[string]interface{} {
|
||||||
|
viewDataContextKey := ctx.Application().ConfigurationReadOnly().GetViewDataContextKey()
|
||||||
|
v := ctx.Values().Get(viewDataContextKey)
|
||||||
|
|
||||||
|
// if no values found, then return nil
|
||||||
|
if v == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// if struct, convert it to map[string]interface{}
|
||||||
|
if structs.IsStruct(v) {
|
||||||
|
return structs.Map(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// if pure map[string]interface{}
|
||||||
|
if viewData, ok := v.(map[string]interface{}); ok {
|
||||||
|
return viewData
|
||||||
|
}
|
||||||
|
|
||||||
|
// if context#Map
|
||||||
|
if viewData, ok := v.(Map); ok {
|
||||||
|
return viewData
|
||||||
|
}
|
||||||
|
|
||||||
|
// if failure, then return nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// View renders templates based on the adapted view engines.
|
// View renders templates based on the adapted view engines.
|
||||||
// First argument accepts the filename, relative to the view engine's Directory,
|
// First argument accepts the filename, relative to the view engine's Directory,
|
||||||
// i.e: if directory is "./templates" and want to render the "./templates/users/index.html"
|
// i.e: if directory is "./templates" and want to render the "./templates/users/index.html"
|
||||||
|
|
|
@ -210,23 +210,22 @@ func (h *routerHandler) HandleRequest(ctx context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.Application().ConfigurationReadOnly().GetFireMethodNotAllowed() {
|
if ctx.Application().ConfigurationReadOnly().GetFireMethodNotAllowed() {
|
||||||
var methodAllowed string
|
|
||||||
for i := range h.trees {
|
for i := range h.trees {
|
||||||
t := h.trees[i]
|
t := h.trees[i]
|
||||||
methodAllowed = t.Method // keep track of the allowed method of the last checked tree
|
// a bit slower than previous implementation but @kataras let me to apply this change
|
||||||
if ctx.Method() != methodAllowed {
|
// because it's more reliable.
|
||||||
continue
|
//
|
||||||
|
// if `Configuration#FireMethodNotAllowed` is kept as defaulted(false) then this function will not
|
||||||
|
// run, therefore performance kept as before.
|
||||||
|
if t.Nodes.Exists(path) {
|
||||||
|
// RCF rfc2616 https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
||||||
|
// The response MUST include an Allow header containing a list of valid methods for the requested resource.
|
||||||
|
ctx.Header("Allow", t.Method)
|
||||||
|
ctx.StatusCode(http.StatusMethodNotAllowed)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.Method() != methodAllowed {
|
|
||||||
// RCF rfc2616 https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
|
||||||
// The response MUST include an Allow header containing a list of valid methods for the requested resource.
|
|
||||||
ctx.Header("Allow", methodAllowed)
|
|
||||||
ctx.StatusCode(http.StatusMethodNotAllowed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.StatusCode(http.StatusNotFound)
|
ctx.StatusCode(http.StatusNotFound)
|
||||||
}
|
}
|
||||||
|
|
|
@ -266,6 +266,15 @@ func (nodes Nodes) Find(path string, params *context.RequestParams) context.Hand
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Exists returns true if a node with that "path" exists,
|
||||||
|
// otherise false.
|
||||||
|
//
|
||||||
|
// We don't care about parameters here.
|
||||||
|
func (nodes Nodes) Exists(path string) bool {
|
||||||
|
n, _ := nodes.findChild(path, nil)
|
||||||
|
return n != nil && len(n.handlers) > 0
|
||||||
|
}
|
||||||
|
|
||||||
func (nodes Nodes) findChild(path string, params []string) (*node, []string) {
|
func (nodes Nodes) findChild(path string, params []string) (*node, []string) {
|
||||||
// println("request path: " + path)
|
// println("request path: " + path)
|
||||||
for _, n := range nodes {
|
for _, n := range nodes {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user