Former-commit-id: 31a50e580929616504b9bbbb1d602b0e9274a568
22 KiB
Changelog
Looking for free and real-time support?
https://github.com/kataras/iris/issues
https://chat.iris-go.com
Looking for previous versions?
https://github.com/kataras/iris/releases
Want to be hired?
https://facebook.com/iris.framework
Should I upgrade my Iris?
Developers are not forced to upgrade if they don't really need it. Upgrade whenever you feel ready.
How to upgrade: Open your command-line and execute this command: go get github.com/kataras/iris/v12@latest
.
Next
This release introduces new features and some breaking changes inside the mvc
and hero
packages.
The codebase for dependency injection has been simplified a lot (fewer LOCs and easier to read and follow up).
The new release contains a fresh new and awesome feature....a function dependency can accept previous registered dependencies and update or return a new value of any type.
The new implementation is faster on both design and serve-time.
The most common scenario from a route to handle is to:
- accept one or more path parameters and request data, a payload
- send back a response, a payload (JSON, XML,...)
The new Iris Dependency Injection feature is about 33.2% faster than its predecessor on the above case. This drops down even more the performance cost between native handlers and dynamic handlers with dependencies. This reason itself brings us, with safety and performance-wise, to the new Party.DI() *APIBuilderDI
method which returns methods such as DI.Handle(method, relativePath string, handlersFn ...interface{}) *Route
and DI.RegisterDependency
.
Look how clean your codebase can be when using Iris':
package main
import "github.com/kataras/iris/v12"
type (
testInput struct {
Email string `json:"email"`
}
testOutput struct {
ID int `json:"id"`
Name string `json:"name"`
}
)
func handler(id int, in testInput) testOutput {
return testOutput{
ID: id,
Name: in.Email,
}
}
func main() {
app := iris.New()
app.DI().Handle(iris.MethodPost, "/{id:int}", handler)
app.Listen(":5000", iris.WithOptimizations)
}
Your eyes don't lie you. You read well, no ctx.ReadJSON(&v)
and ctx.JSON(send)
neither error
handling are presented. It is a huge relief but if you ever need, you still have the control over those, even errors from dependencies. Any error may occur from request-scoped dependencies or your own handler is dispatched through Party.DI().Container.GetErrorHandler
which defaults to the hero.DefaultErrorHandler
which sends a 400 Bad Request
response with the error's text as its body contents, you can change it through Party.DI().OnError
. If you want to handle testInput
otherwise then just add a Party.DI().RegisterDependency(func(ctx iris.Context) testInput {...})
and you are ready to go. Here is a quick list of the new Party.DI's fields and methods:
// Container holds the DI Container of this Party featured Dependency Injection.
// Use it to manually convert functions or structs(controllers) to a Handler.
Container *hero.Container
// OnError adds an error handler for this Party's DI Hero Container and its handlers (or controllers).
// The "errorHandler" handles any error may occurred and returned
// during dependencies injection of the Party's hero handlers or from the handlers themselves.
OnError(errorHandler func(context.Context, error))
// RegisterDependency adds a dependency.
// The value can be a single struct value or a function.
// Follow the rules:
// * <T> {structValue}
// * func(accepts <T>) returns <D> or (<D>, error)
// * func(accepts iris.Context) returns <D> or (<D>, error)
// * func(accepts1 iris.Context, accepts2 *hero.Input) returns <D> or (<D>, error)
//
// A Dependency can accept a previous registered dependency and return a new one or the same updated.
// * func(accepts1 <D>, accepts2 <T>) returns <E> or (<E>, error) or error
// * func(acceptsPathParameter1 string, id uint64) returns <T> or (<T>, error)
//
// Usage:
//
// - RegisterDependency(loggerService{prefix: "dev"})
// - RegisterDependency(func(ctx iris.Context) User {...})
// - RegisterDependency(func(User) OtherResponse {...})
RegisterDependency(dependency interface{})
// Use same as a common Party's "Use" but it accepts dynamic functions as its "handlersFn" input.
Use(handlersFn ...interface{})
// Done same as a common Party's but it accepts dynamic functions as its "handlersFn" input.
Done(handlersFn ...interface{})
// Handle same as a common Party's `Handle` but it accepts one or more "handlersFn" functions which each one of them
// can accept any input arguments that match with the Party's registered Container's `Dependencies` and
// any output result; like custom structs <T>, string, []byte, int, error,
// a combination of the above, hero.Result(hero.View | hero.Response) and more.
//
// It's common from a hero handler to not even need to accept a `Context`, for that reason,
// the "handlersFn" will call `ctx.Next()` automatically when not called manually.
// To stop the execution and not continue to the next "handlersFn"
// the end-developer should output an error and return `iris.ErrStopExecution`.
Handle(method, relativePath string, handlersFn ...interface{}) *Route
Prior to this version the iris.Context
was the only one dependency that has been automatically binded to the handler's input or a controller's fields and methods, read below to see what types are automatically binded:
Type | Maps To |
---|---|
iris.Context | Current Iris Context |
*sessions.Session | Current Iris Session |
context.Context | ctx.Request().Context() |
*http.Request | ctx.Request() |
http.ResponseWriter | ctx.ResponseWriter() |
http.Header | ctx.Request().Header |
time.Time | time.Now() |
string , |
|
int, int8, int16, int32, int64 , |
|
uint, uint8, uint16, uint32, uint64 , |
|
float, float32, float64 , |
|
bool , |
|
slice |
Path Parameter |
Struct | Request Body of JSON , XML , YAML , Form , URL Query , Protobuf , MsgPack |
Here is a preview of what the new Hero handlers look like:
Request & Response & Path Parameters
Custom Preflight
Custom Dependencies
Other Improvements:
-
New
app.Validator { Struct(interface{}) error }
field andapp.Validate
method were added. Theapp.Validator =
can be used to integrate a 3rd-party package such as go-playground/validator. If set-ed then IrisContext
'sReadJSON
,ReadXML
,ReadMsgPack
,ReadYAML
,ReadForm
,ReadQuery
,ReadBody
methods will return the validation error on data validation failures. The read-json-struct-validation example was updated. -
A result of can implement the new
hero.PreflightResult
interface which contains a single method ofPreflight(iris.Context) error
. If this method exists on a custom struct value which is returned from a handler then it will fire thatPreflight
first and if not errored then it will cotninue by sending the struct value as JSON(by-default) response body. -
ctx.JSON, JSONP, XML
: ifiris.WithOptimizations
is NOT passed onapp.Run/Listen
then the indentation defaults to" "
(two spaces) otherwise it is empty or the provided value. -
Hero Handlers (and
app.DI().Handle
) do not have to requireiris.Context
just to callctx.Next()
anymore, this is done automatically now.
New Context Methods:
context.UpsertCookie(*http.Cookie, cookieOptions ...context.CookieOption)
upserts a cookie, fixes #1485 toocontext.StopWithStatus(int)
stops the handlers chain and writes the status codecontext.StopWithJSON(int, interface{})
stops the handlers chain, writes the status code and sends a JSON responsecontext.StopWithProblem(int, iris.Problem)
stops the handlers, writes the status code and sends anapplication/problem+json
responsecontext.Protobuf(proto.Message)
sends protobuf to the clientcontext.MsgPack(interface{})
sends msgpack format data to the clientcontext.ReadProtobuf(ptr)
binds request body to a proto messagecontext.ReadMsgPack(ptr)
binds request body of a msgpack format to a structcontext.ReadBody(ptr)
binds the request body to the "ptr" depending on the request's Method and Content-Typecontext.SetSameSite(http.SameSite)
to set cookie "SameSite" option (respectful by sessions too)context.Defer(Handler)
works likeParty.Done
but for the request life-cycle insteadcontext.ReflectValue() []reflect.Value
stores and returns the[]reflect.ValueOf(context)
context.Controller() reflect.Value
returns the current MVC Controller value.
Breaking Changes:
var mvc.AutoBinding
removed as the default behavior now resolves such dependencies automatically (see [FEATURE REQUEST] MVC serving gRPC-compatible controller)mvc#Application.SortByNumMethods()
removed as the default behavior now binds the "thinnest" emptyinterface{}
automatically (see MVC: service injecting fails)mvc#BeforeActivation.Dependencies().Add
should be replaced withmvc#BeforeActivation.Dependencies().Register
instead.
Su, 16 February 2020 | v12.1.8
New Features:
Fixes:
New Examples:
Mo, 10 February 2020 | v12.1.7
Implement new SetRegisterRule(iris.RouteOverride, RouteSkip, RouteError)
to resolve: https://github.com/kataras/iris/issues/1448
New Examples:
We, 05 February 2020 | v12.1.6
Fixes:
Su, 02 February 2020 | v12.1.5
Various improvements and linting.
Su, 29 December 2019 | v12.1.4
Minor fix on serving embedded files.
We, 25 December 2019 | v12.1.3
Fix [BUG] [iris.Default] RegisterView
Th, 19 December 2019 | v12.1.2
Fix [BUG]Session works incorrectly when meets the multi-level TLDs.
Mo, 16 December 2019 | v12.1.1
Add Context.FindClosest(n int) []string
app := iris.New()
app.OnErrorCode(iris.StatusNotFound, notFound)
func notFound(ctx iris.Context) {
suggestPaths := ctx.FindClosest(3)
if len(suggestPaths) == 0 {
ctx.WriteString("404 not found")
return
}
ctx.HTML("Did you mean?<ul>")
for _, s := range suggestPaths {
ctx.HTML(`<li><a href="%s">%s</a></li>`, s, s)
}
ctx.HTML("</ul>")
}
Fr, 13 December 2019 | v12.1.0
Breaking Changes
Minor as many of you don't even use them but, indeed, they need to be covered here.
- Old i18n middleware(iris/middleware/i18n) was replaced by the i18n sub-package which lives as field at your application:
app.I18n.Load(globPathPattern string, languages ...string)
(see below) - Community-driven i18n middleware(iris-contrib/middleware/go-i18n) has a
NewLoader
function which returns a loader which can be passed atapp.I18n.Reset(loader i18n.Loader, languages ...string)
to change the locales parser - The Configuration's
TranslateFunctionContextKey
was replaced byLocaleContextKey
which Context store's value (if i18n is used) returns the current Locale which contains the translate function, the language code, the language tag and the index position of it - The
context.Translate
method was replaced bycontext.Tr
as a shortcut for the newcontext.GetLocale().GetMessage(format, args...)
method and it matches the view's function{{tr format args}}
too - If you used Iris Django view engine with
import _ github.com/flosch/pongo2-addons
you must change the import path to_ github.com/iris-contrib/pongo2-addons
or add a go mod replace to yourgo.mod
file, e.g.replace github.com/flosch/pongo2-addons => github.com/iris-contrib/pongo2-addons v0.0.1
.
Fixes
All known issues.
New Features
Internationalization and localization
Support for i18n is now a builtin feature and is being respected across your entire application, per say sitemap and views.
Refer to the wiki section: https://github.com/kataras/iris/wiki/Sitemap for details.
Sitemaps
Iris generates and serves one or more sitemap.xml for your static routes.
Navigate through: https://github.com/kataras/iris/wiki/Sitemap for more.
New Examples
- _examples/i18n
- _examples/sitemap
- _examples/desktop-app/blink
- _examples/desktop-app/lorca
- _examples/desktop-app/webview
Sa, 26 October 2019 | v12.0.0
- Add version suffix of the import path, learn why and see what people voted at issue #1370
- All errors are now compatible with go1.13
errors.Is
,errors.As
andfmt.Errorf
and a newcore/errgroup
package created - Fix #1383
- Report whether system couldn't find the directory of view templates
- Remove the
Party#GetReport
method, keepParty#GetReporter
which is anerror
and anerrgroup.Group
. - Remove the router's deprecated methods such as StaticWeb and StaticEmbedded_XXX
- The
Context#CheckIfModifiedSince
now returns ancontext.ErrPreconditionFailed
type of error when client conditions are not met. Usage:if errors.Is(err, context.ErrPreconditionFailed) { ... }
- Add
SourceFileName
andSourceLineNumber
to theRoute
, reports the exact position of its registration inside your project's source code. - Fix a bug about the MVC package route binding, see PR #1364
- Add
mvc/Application#SortByNumMethods
as requested at #1343 - Add status code
103 Early Hints
- Fix performance of session.UpdateExpiration on 200 thousands+ keys with new radix as reported at issue #1328
- New redis session database configuration field:
Driver: redis.Redigo()
orredis.Radix()
, see updated examples - Add Clusters support for redis:radix session database (
Driver: redis:Radix()
) as requested at issue #1339 - Create Iranian README_FA translation with PR #1360
- Create Korean README_KO translation with PR #1356
- Create Spanish README_ES and HISTORY_ES translations with PR #1344.
The iris-contrib/middleare and examples are updated to use the new github.com/kataras/iris/v12
import path.
Fr, 16 August 2019 | v11.2.8
- Set
Cookie.SameSite
toLax
when subdomains sessions share is enabled* - Add and update all experimental handlers
- New
XMLMap
function which wraps amap[string]interface{}
and converts it to a valid xml content to render throughContext.XML
method - Add new
ProblemOptions.XML
andRenderXML
fields to render theProblem
as XML(application/problem+xml) instead of JSON("application/problem+json) and enrich theNegotiate
to easily accept theapplication/problem+xml
mime.
Commit log: https://github.com/kataras/iris/compare/v11.2.7...v11.2.8
Th, 15 August 2019 | v11.2.7
This minor version contains improvements on the Problem Details for HTTP APIs implemented on v11.2.5.
- Fix https://github.com/kataras/iris/issues/1335#issuecomment-521319721
- Add
ProblemOptions
withRetryAfter
as requested at: https://github.com/kataras/iris/issues/1335#issuecomment-521330994. - Add
iris.JSON
alias forcontext#JSON
options type.
References:
Commit log: https://github.com/kataras/iris/compare/v11.2.6...v11.2.7
We, 14 August 2019 | v11.2.6
app.Get("/{alias:string regexp(^[a-z0-9]{1,10}\\.xml$)}", PanoXML)
app.Get("/{alias:string regexp(^[a-z0-9]{1,10}$)}", Tour)
Commit log: https://github.com/kataras/iris/compare/v11.2.5...v11.2.6
Mo, 12 August 2019 | v11.2.5
Commit log: https://github.com/kataras/iris/compare/v11.2.4...v11.2.5
Fr, 09 August 2019 | v11.2.4
- Fixes iris.Jet: no view engine found for '.jet' or '.html'
- Fixes ctx.ViewData not work with JetEngine
- New Feature: HTTP Method Override
- Fixes Poor performance of session.UpdateExpiration on 200 thousands+ keys with new radix lib by introducing the
sessions.Config.Driver
configuration field which defaults toRedigo()
but can be set toRadix()
too, future additions are welcomed.
Commit log: https://github.com/kataras/iris/compare/v11.2.3...v11.2.4
Tu, 30 July 2019 | v11.2.3
- New Feature: Handle different parameter types in the same path
- New Feature: Content Negotiation
- Context.ReadYAML
- Fixes https://github.com/kataras/neffos/issues/1#issuecomment-515698536
We, 24 July 2019 | v11.2.2
Sessions as middleware:
import "github.com/kataras/iris/v12/sessions"
// [...]
app := iris.New()
sess := sessions.New(sessions.Config{...})
app.Get("/path", func(ctx iris.Context){
session := sessions.Get(ctx)
// [work with session...]
})
- Add
Session.Len() int
to return the total number of stored values/entries. - Make
Context.HTML
andContext.Text
to accept an optional, variadic,args ...interface{}
input arg(s) too.
v11.1.1
Tu, 23 July 2019 | v11.2.0
Read about the new release at: https://www.facebook.com/iris.framework/posts/3276606095684693