diff --git a/HISTORY.md b/HISTORY.md index 346f92b5..6a705e65 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -21,6 +21,13 @@ Developers are not forced to upgrade if they don't really need it. Upgrade whene **How to upgrade**: Open your command-line and execute this command: `go get github.com/kataras/iris/v12@latest`. +# We, 05 February 2020 | v12.1.6 + +Fixes: + +- [jet.View - urlpath error](https://github.com/kataras/iris/issues/1438) +- [Context.ServeFile send 'application/wasm' with a wrong extra field](https://github.com/kataras/iris/issues/1440) + # Su, 02 February 2020 | v12.1.5 Various improvements and linting. diff --git a/HISTORY_ES.md b/HISTORY_ES.md index b9ce74f5..d9f23833 100644 --- a/HISTORY_ES.md +++ b/HISTORY_ES.md @@ -21,9 +21,9 @@ Los desarrolladores no están obligados a actualizar si realmente no lo necesita **Cómo actualizar**: Abra su línea de comandos y ejecute este comando: `go get github.com/kataras/iris/v12@latest`. -# Su, 02 February 2020 | v12.1.5 +# We, 05 February 2020 | v12.1.6 -Not translated yet, please navigate to the [english version](HISTORY.md#su-02-february-2020--v1215) instead. +Not translated yet, please navigate to the [english version](HISTORY.md#we-05-february-2020--v1216) instead. # Sábado, 26 de octubre 2019 | v12.0.0 diff --git a/NOTICE b/NOTICE index 614039b9..62c03895 100644 --- a/NOTICE +++ b/NOTICE @@ -51,6 +51,9 @@ Revision ID: 607b5b7cef034da2692f99a4c9bafb31a999ccda jade 9ffefa50b5f3141 https://github.com/Joker/jade 6ac643e9d9ad611 6f4688705f + jet 33cfc27b3e00072 github.com/CloudyKit/jet + 655fdb3af24c325 + 3ea5bffb8f json-iterator 08047c174c6c03e https://github.com/json-iterator/go 8ec963a411bde1b 6d1ee67b26 diff --git a/README.md b/README.md index c7528516..3d4d59b6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # News -![](https://iris-go.com/images/release.png) Iris version **12.1.5** has been [released](HISTORY.md#su-02-february-2020--v1215)! +![](https://iris-go.com/images/release.png) Iris version **12.1.6** has been [released](HISTORY.md#we-05-february-2020--v1216)! ![](https://iris-go.com/images/cli.png) The official [Iris Command Line Interface](https://github.com/kataras/iris-cli) will soon be near you in 2020! diff --git a/VERSION b/VERSION index cb1c968e..ec3291b4 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -12.1.5:https://github.com/kataras/iris/releases/tag/v12.1.5 \ No newline at end of file +12.1.6:https://github.com/kataras/iris/releases/tag/v12.1.6 \ No newline at end of file diff --git a/_examples/http-listening/custom-listener/unix-reuseport/main.go b/_examples/http-listening/custom-listener/unix-reuseport/main.go index c20932f7..7b67d5fc 100644 --- a/_examples/http-listening/custom-listener/unix-reuseport/main.go +++ b/_examples/http-listening/custom-listener/unix-reuseport/main.go @@ -19,9 +19,7 @@ import ( "github.com/kataras/iris/v12" ) -// $ go get github.com/valyala/tcplisten -// $ go run main.go - +// You can run the same app as many times as you want. func main() { app := iris.New() @@ -35,7 +33,7 @@ func main() { FastOpen: true, } - l, err := listenerCfg.NewListener("tcp", ":8080") + l, err := listenerCfg.NewListener("tcp4", ":8080") if err != nil { panic(err) } diff --git a/_examples/view/template_jet_0/main.go b/_examples/view/template_jet_0/main.go index 7cbaaab0..bd8762a8 100644 --- a/_examples/view/template_jet_0/main.go +++ b/_examples/view/template_jet_0/main.go @@ -125,16 +125,13 @@ func main() { ctx.ViewData("showingAllDone", true) ctx.ViewData("title", "Todos - All Done") - // Key does not actual matter at all here. - // However, you can enable it for better performance. - // In order to enable key mapping for - // jet specific renderer and ranger types - // you have to initialize the View Engine - // with `tmpl.DisableViewDataTypeCheck("_jet")`. - // - // Defaults to type checks, empty key. - ctx.ViewData("_jet", (&doneTODOs{}).New(todos)) - ctx.View("todos/index.jet") + // Use ctx.ViewData("_jet", jetData) + // if using as middleware and you want + // to pre-set the value or even change it later on from another next middleware. + // ctx.ViewData("_jet", (&doneTODOs{}).New(todos)) + // and ctx.View("todos/index.jet") + // OR + ctx.View("todos/index.jet", (&doneTODOs{}).New(todos)) }) port := os.Getenv("PORT") diff --git a/_examples/view/template_jet_0/views/todos/show.jet b/_examples/view/template_jet_0/views/todos/show.jet index 334e7813..403cd588 100644 --- a/_examples/view/template_jet_0/views/todos/show.jet +++ b/_examples/view/template_jet_0/views/todos/show.jet @@ -2,7 +2,7 @@ {{block documentBody()}}

Show TODO

-

This uses a custom renderer by implementing the jet.Renderer interface. +

This uses a custom renderer by implementing the jet.Renderer (or view.JetRenderer) interface.

{{.}}

diff --git a/_examples/view/template_jet_2/main.go b/_examples/view/template_jet_2/main.go new file mode 100644 index 00000000..6363326a --- /dev/null +++ b/_examples/view/template_jet_2/main.go @@ -0,0 +1,66 @@ +// Package main an example on how to naming your routes & use the custom 'url path' Jet Template Engine. +package main + +import ( + "github.com/kataras/iris/v12" +) + +func main() { + app := iris.New() + app.RegisterView(iris.Jet("./views", ".jet").Reload(true)) + + mypathRoute := app.Get("/mypath", writePathHandler) + mypathRoute.Name = "my-page1" + + mypath2Route := app.Get("/mypath2/{paramfirst}/{paramsecond}", writePathHandler) + mypath2Route.Name = "my-page2" + + mypath3Route := app.Get("/mypath3/{paramfirst}/statichere/{paramsecond}", writePathHandler) + mypath3Route.Name = "my-page3" + + mypath4Route := app.Get("/mypath4/{paramfirst}/statichere/{paramsecond}/{otherparam}/{something:path}", writePathHandler) + // same as: app.Get("/mypath4/:paramfirst/statichere/:paramsecond/:otherparam/*something", writePathHandler) + mypath4Route.Name = "my-page4" + + // same with Handle/Func + mypath5Route := app.Handle("GET", "/mypath5/{paramfirst}/statichere/{paramsecond}/{otherparam}/anything/{something:path}", writePathHandler) + mypath5Route.Name = "my-page5" + + mypath6Route := app.Get("/mypath6/{paramfirst}/{paramsecond}/statichere/{paramThirdAfterStatic}", writePathHandler) + mypath6Route.Name = "my-page6" + + app.Get("/", func(ctx iris.Context) { + // for /mypath6... + paramsAsArray := []string{"theParam1", "theParam2", "paramThirdAfterStatic"} + ctx.ViewData("ParamsAsArray", paramsAsArray) + if err := ctx.View("page.jet"); err != nil { + panic(err) + } + }) + + app.Get("/redirect/{namedRoute}", func(ctx iris.Context) { + routeName := ctx.Params().Get("namedRoute") + r := app.GetRoute(routeName) + if r == nil { + ctx.StatusCode(iris.StatusNotFound) + ctx.Writef("Route with name %s not found", routeName) + return + } + + println("The path of " + routeName + "is: " + r.Path) + // if routeName == "my-page1" + // prints: The path of of my-page1 is: /mypath + // if it's a path which takes named parameters + // then use "r.ResolvePath(paramValuesHere)" + ctx.Redirect(r.Path) + // http://localhost:8080/redirect/my-page1 will redirect to -> http://localhost:8080/mypath + }) + + // http://localhost:8080 + // http://localhost:8080/redirect/my-page1 + app.Run(iris.Addr(":8080")) +} + +func writePathHandler(ctx iris.Context) { + ctx.Writef("Hello from %s.", ctx.Path()) +} diff --git a/_examples/view/template_jet_2/views/page.jet b/_examples/view/template_jet_2/views/page.jet new file mode 100644 index 00000000..d0a0f220 --- /dev/null +++ b/_examples/view/template_jet_2/views/page.jet @@ -0,0 +1,24 @@ +/mypath +
+
+/mypath2/{paramfirst}/{paramsecond} +
+
+ +/mypath3/{paramfirst}/statichere/{paramsecond} +
+
+ + + /mypath4/{paramfirst}/statichere/{paramsecond}/{otherparam}/{something:path} +
+
+ + + /mypath5/{paramfirst}/statichere/{paramsecond}/{otherparam}/anything/{anything:path} +
+
+ + + /mypath6/{paramfirst}/{paramsecond}/statichere/{paramThirdAfterStatic} + diff --git a/doc.go b/doc.go index 4a20bb09..1f2f6fd2 100644 --- a/doc.go +++ b/doc.go @@ -38,7 +38,7 @@ Source code and other details for the project are available at GitHub: Current Version -12.1.5 +12.1.6 Installation diff --git a/go.mod b/go.mod index ba8d2054..bced6f93 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.13 require ( github.com/BurntSushi/toml v0.3.1 - github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible + github.com/CloudyKit/jet/v3 v3.0.0 github.com/Joker/jade v1.0.1-0.20190614124447-d475f43051e7 github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398 github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible diff --git a/iris.go b/iris.go index 94f036dc..34cf205e 100644 --- a/iris.go +++ b/iris.go @@ -41,7 +41,7 @@ import ( ) // Version is the current version number of the Iris Web Framework. -const Version = "12.1.5" +const Version = "12.1.6" // HTTP status codes as registered with IANA. // See: http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml. @@ -583,9 +583,17 @@ func (app *Application) NewHost(srv *http.Server) *host.Supervisor { srv.ErrorLog = log.New(app.logger.Printer.Output, "[HTTP Server] ", 0) } - if srv.Addr == "" { - srv.Addr = ":8080" + if addr := srv.Addr; addr == "" { + addr = ":8080" + if len(app.Hosts) > 0 { + if v := app.Hosts[0].Server.Addr; v != "" { + addr = v + } + } + + srv.Addr = addr } + app.logger.Debugf("Host: addr is %s", srv.Addr) // create the new host supervisor diff --git a/view/jet.go b/view/jet.go index f72b46b6..f411aab3 100644 --- a/view/jet.go +++ b/view/jet.go @@ -10,7 +10,7 @@ import ( "github.com/kataras/iris/v12/context" - "github.com/CloudyKit/jet" + "github.com/CloudyKit/jet/v3" ) const jetEngineName = "jet" @@ -64,29 +64,15 @@ func Jet(directory, extension string) *JetEngine { } s := &JetEngine{ - directory: directory, - extension: extension, - loader: jet.NewOSFileSystemLoader(directory), + directory: directory, + extension: extension, + loader: jet.NewOSFileSystemLoader(directory), + jetRangerRendererContextKey: "_jet", } return s } -// DisableViewDataTypeCheck accepts a context key name to use -// to map the jet specific renderer and ranger over context's view data. -// -// If "jetDataContextKey" is not empty then `ExecuteWriter` will not check for -// types to check if an element passed through `Context.ViewData` -// contains a jet.Renderer or jet.Ranger or both. -// Instead will map those with simple key data naming (faster). -// Also it wont check if a value is already a reflect.Value (jet expects this type as values). -// -// Defaults to empty. -func (s *JetEngine) DisableViewDataTypeCheck(jetRangerRendererContextKey string) *JetEngine { - s.jetRangerRendererContextKey = jetRangerRendererContextKey - return s -} - // String returns the name of this view engine, the "jet". func (s *JetEngine) String() string { return jetEngineName @@ -118,7 +104,7 @@ func (s *JetEngine) AddFunc(funcName string, funcBody interface{}) { // instead it wants: // func(JetArguments) reflect.Value. - s.AddVar(funcName, func(args JetArguments) reflect.Value { + s.AddVar(funcName, jet.Func(func(args JetArguments) reflect.Value { n := args.NumOfArguments() if n == 0 { // no input, don't execute the function, panic instead. panic(funcName + " expects one or more input arguments") @@ -140,7 +126,7 @@ func (s *JetEngine) AddFunc(funcName string, funcBody interface{}) { } return reflect.ValueOf(generalFunc(firstInput, variadicInputs...)) - }) + })) return } @@ -366,53 +352,7 @@ func (s *JetEngine) AddRuntimeVars(ctx context.Context, vars JetRuntimeVars) { AddJetRuntimeVars(ctx, vars) } -type rangerAndRenderer struct { - ranger jet.Ranger - renderer jet.Renderer -} - -func (rr rangerAndRenderer) Range() (reflect.Value, reflect.Value, bool) { - return rr.ranger.Range() -} - -func (rr rangerAndRenderer) Render(jetRuntime *jet.Runtime) { - rr.renderer.Render(jetRuntime) -} - -func rangerRenderer(bindingData interface{}) (interface{}, bool) { - if ranger, ok := bindingData.(jet.Ranger); ok { - // Externally fixes a BUG on the jet template parser: - // eval.go#executeList(list *ListNode):NodeRange.isSet.getRanger(expression = st.evalPrimaryExpressionGroup) - // which does not act the "ranger" as element, instead is converted to a value of struct, which makes a jet.Ranger func(*myStruct) Range... - // not a compatible jet.Ranger. - // getRanger(st.context) should work but author of the jet library is not currently available, - // to allow a recommentation or a PR and I don't really want to vendor it because - // some end-users may use the jet import path to pass things like Global Funcs and etc. - // So to fix it (at least temporarily and only for ref Ranger) we ptr the ptr the "ranger", not the bindingData, and this may - // have its downside because the same bindingData may be compatible with other node actions like range or custom Render - // but we have no other way at the moment. The same problem exists on the `Renderer` too! - // The solution below fixes the above issue but any fields of the struct are not available, - // this is ok because most of the times if not always, the users of jet don't use fields on Ranger and custom Renderer inside the templates. - - if renderer, ok := bindingData.(jet.Renderer); ok { - // this can make a Ranger and Renderer both work together, unlike the jet parser itself. - return rangerAndRenderer{ranger, renderer}, true - } - - return &ranger, true - } - - if renderer, ok := bindingData.(jet.Renderer); ok { - // Here the fields are not available but usually if completes the jet.Renderer no - // fields are used in the template. - return &renderer, true // see above ^. - } - - return nil, false -} - // ExecuteWriter should execute a template by its filename with an optional layout and bindingData. -// See `DisableViewDataTypeCheck` too. func (s *JetEngine) ExecuteWriter(w io.Writer, filename string, layout string, bindingData interface{}) error { tmpl, err := s.Set.GetTemplate(filename) if err != nil { @@ -434,46 +374,28 @@ func (s *JetEngine) ExecuteWriter(w io.Writer, filename string, layout string, b return tmpl.Execute(w, vars, nil) } - jetRangerRenderer, ok := rangerRenderer(bindingData) - if ok { - return tmpl.Execute(w, vars, jetRangerRenderer) + if vars == nil { + vars = make(JetRuntimeVars) } if m, ok := bindingData.(context.Map); ok { + var jetData interface{} for k, v := range m { - if s.jetRangerRendererContextKey == "" { - switch value := v.(type) { - case jet.Ranger, jet.Renderer: - jetRangerRenderer, _ = rangerRenderer(value) - case reflect.Value: - if vars == nil { - vars = make(JetRuntimeVars) - } - // if it's already a reflect value. - vars[k] = value - default: - if vars == nil { - vars = make(JetRuntimeVars) - } - vars.Set(k, v) - } - - continue - } - if k == s.jetRangerRendererContextKey { - jetRangerRenderer = v + jetData = v continue } - if vars == nil { - vars = make(JetRuntimeVars) + if value, ok := v.(reflect.Value); ok { + vars[k] = value + } else { + vars[k] = reflect.ValueOf(v) } - - vars.Set(k, v) } - return tmpl.Execute(w, vars, jetRangerRenderer) + if jetData != nil { + bindingData = jetData + } } return tmpl.Execute(w, vars, bindingData)