https://github.com/kataras/iris/issues
https://chat.iris-go.com
https://github.com/kataras/iris/releases
https://facebook.com/iris.framework
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
and go mod tidy -compat=1.21
.
Changes apply to main
branch.
Dear Iris Community,
You might have noticed a recent lull in activity on the Iris repository. I want to assure you that this silence is not without reason. For the past 3-4 months, I've been diligently working on the next major release of Iris.
This upcoming version is poised to be a significant leap forward, fully embracing the Generics feature introduced in Go. We're not just stopping at Generics, though. Expect a suite of new features, enhancements, and optimizations that will elevate your development experience to new heights.
My journey with Go spans over 8 years, and with each year, my expertise and understanding of the language deepen. This accumulated knowledge is being poured into Iris, ensuring that the framework not only evolves with the language but also with the community's growing needs.
Stay tuned for more updates, and thank you for your continued support and patience. The wait will be worth it.
Warm regards,
Gerasimos (Makis) Maropoulos
-
Security improvements and dependencies upgrade.
-
New
Application/Party.MiddlewareExists(handlerNameOrHandler)
method added, example:
package main
import (
"fmt"
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/x/errors"
)
func main() {
app := iris.New()
app.UseRouter(errors.RecoveryHandler)
if app.MiddlewareExists(errors.RecoveryHandler) { // <- HERE.
fmt.Println("errors.RecoveryHandler exists")
}
// OR:
// if app.MiddlewareExists("iris.errors.recover") {
// fmt.Println("Iris.Errors.Recovery exists")
// }
app.Get("/", indexHandler)
app.Listen(":8080")
}
func indexHandler(ctx iris.Context) {
panic("an error here")
ctx.HTML("<h1>Index</h1>")
}
- New
x/errors.Intercept(func(ctx iris.Context, req *CreateRequest, resp *CreateResponse) error{ ... })
package-level function.
func main() {
app := iris.New()
// Create a new service and pass it to the handlers.
service := new(myService)
app.Post("/", errors.Intercept(responseHandler), errors.CreateHandler(service.Create))
// [...]
}
func responseHandler(ctx iris.Context, req *CreateRequest, resp *CreateResponse) error {
fmt.Printf("intercept: request got: %+v\nresponse sent: %#+v\n", req, resp)
return nil
}
- Rename
x/errors/ContextValidator.ValidateContext(iris.Context) error
tox/errors/RequestHandler.HandleRequest(iris.Context) error
.
- Simplify the
/core/host
subpackage and remove itsDeferFlow
andRestoreFlow
methods. These methods are replaced with:Supervisor.Configure(host.NonBlocking())
beforeServe
andSupervisor.Wait(context.Context) error
afterServe
. - Fix internal
trimHandlerName
and other minor stuff. - New
iris.NonBlocking()
configuration option to run the server without blocking the main routine,Application.Wait(context.Context) error
method can be used to block and wait for the server to be up and running. Example:
func main() {
app := iris.New()
app.Get("/", func(ctx iris.Context) {
ctx.Writef("Hello, %s!", "World")
})
app.Listen(":8080", iris.NonBlocking(), iris.WithoutServerError(iris.ErrServerClosed))
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel()
if err := app.Wait(ctx); err != nil {
log.Fatal(err)
}
// [Server is up and running now, you may continue with other functions below].
}
- Add
x/mathx.RoundToInteger
math helper function.
- Add
x/errors.RecoveryHandler
package-level function. - Add
x/errors.Validation
package-level function to add one or more validations for the request payload before a service call of the below methods. - Add
x/errors.Handler
,CreateHandler
,NoContentHandler
,NoContentOrNotModifiedHandler
andListHandler
ready-to-use handlers for service method calls to Iris Handler. - Add
x/errors.List
package-level function to supportListObjects(ctx context.Context, opts pagination.ListOptions, f Filter) ([]Object, int64, error)
type of service calls. - Simplify how validation errors on
/x/errors
package works. A newx/errors/validation
sub-package added to make your life easier (using the powerful Generics feature). - Add
x/errors.OK
,Create
,NoContent
andNoContentOrNotModified
package-level generic functions as custom service method caller helpers. Example can be found here. - Add
x/errors.ReadPayload
,ReadQuery
,ReadPaginationOptions
,Handle
,HandleCreate
,HandleCreateResponse
,HandleUpdate
andHandleDelete
package-level functions as helpers for common actions. - Add
x/jsonx.GetSimpleDateRange(date, jsonx.WeekRange, time.Monday, time.Sunday)
which returns all dates between the given range and start/end weekday values for WeekRange. - Add
x/timex.GetMonthDays
andx/timex.GetMonthEnd
functions. - Add
iris.CookieDomain
andiris.CookieOverride
cookie options to handle #2309. - New
x/errors.ErrorCodeName.MapErrorFunc
,MapErrors
,Wrap
methods andx/errors.HandleError
package-level function.
-
A new way to customize the handler's parameter among with the
hero
andmvc
packages. Newiris.NewContextWrapper
andiris.NewContextPool
methods were added to wrap a handler (.Handler
,.Handlers
,.HandlerReturnError
,HandlerReturnDuration
,Filter
andFallbackViewFunc
methods) and use a custom context instead of the iris.Context directly. Example at: https://github.com/kataras/iris/tree/main/_examples/routing/custom-context. -
The
cache
sub-package has an update, 4 years after:- Add support for custom storage on
cache
package, through theHandler#Store
method. - Add support for custom expiration duration on
cache
package, trough theHandler#MaxAge
method. - Improve the overral performance of the
cache
package. - The
cache.Handler
input and output arguments remain as it is. - The
cache.Cache
input argument changed fromtime.Duration
tofunc(iris.Context) time.Duration
.
- Add support for custom storage on
Minor bug fixes and support of multiple block
and define
directives in multiple layouts and templates in the Blocks
view engine.
-
Add optional
Singleton() bool
method to controllers to mark them as singleton, will panic with a specific error if a controller expects dynamic dependencies. This behavior is idendical to the app-drivenapp.EnsureStaticBindings()
. -
Non-zero fields of a controller that are marked as ignored, with
ignore:"true"
field tag, they are not included in the dependencies at all now. -
Re-add error log on context rich write (e.g. JSON) failures when the application is running under debug mode (with
app.Logger().SetLevel("debug")
) and there is no a registered context error handler at place. -
master
branch finally renamed tomain
. Don't worry GitHub will still navigate anymaster
request tomain
automatically. Examples, Documentation and other Pages are refactored too.
- Add new
iris.WithDynamicHandler
option (EnableDynamicHandler
setting) to work withiris.Application.RefreshRouter
method. It allows to change the entire router while your server is up and running. Handles issue #2167. Example at _examples/routing/route-state/main.go.
We jumped v12.2.2 and v12.2.3.
-
Add
mvc.Application.EnableStructDependents()
method to handle #2158. -
Fix iris-premium#17.
-
Replace russross/blackfriday with gomarkdown as requested at #2098.
-
Add
mvc.IgnoreEmbedded
option to handle #2103. Example Code:
func configure(m *mvc.Application) {
m.Router.Use(cacheHandler)
m.Handle(&exampleController{
timeFormat: "Mon, Jan 02 2006 15:04:05",
}, mvc.IgnoreEmbedded /* BaseController.GetDoSomething will not be parsed at all */)
}
type BaseController struct {
Ctx iris.Context
}
func (c *BaseController) GetDoSomething(i interface{}) error {
return nil
}
type exampleController struct {
BaseController
timeFormat string
}
func (c *exampleController) Get() string {
now := time.Now().Format(c.timeFormat)
return "last time executed without cache: " + now
}
-
Add
LoadKV
method onIris.Application.I18N
instance. It should be used when no locale files are available. It loads locales via pure Go Map (or database decoded values). -
Remove ace template parser support, as it was discontinued by its author more than five years ago.
This release introduces new features and some breaking changes. The codebase for Dependency Injection, Internationalization and localization and more have been simplified a lot (fewer LOCs and easier to read and follow up).
All new features have been tested in production and seem to work fine. Fixed all reported and reproducible bugs. The v12.2.0-beta7
is the latest beta release of v12.2.0. Expect the final public and stable release of v12.2.0 shortly after February 2023.
-
Add
iris.TrimParamFilePart
to handle cases like #2024 and improve the _examples/routing/dynamic-path/main.go example to include that case as well. -
Breaking-change: HTML template functions
yield
,part
,partial
,partial_r
andrender
now accept (and require for some cases) a second argument of the binding data context too. Convert:{{ yield }}
to{{ yield . }}
,{{ render "templates/mytemplate.html" }}
to{{ render "templates/mytemplate.html" . }}
,{{ partial "partials/mypartial.html" }}
to{{ partial "partials/mypartial.html" . }}
and so on. -
Add new
URLParamSeparator
to the configuration. Defaults to "," but can be set to an empty string to disable splitting query values onContext.URLParamSlice
method. -
PR #1992: Added support for third party packages on httptest. An example using 3rd-party module named Ginkgo can be found here.
-
Add
Context.Render
method for compatibility. -
Support of embedded locale files using standard
embed.FS
with the newLoadFS
function. -
Support of direct embedded view engines (
HTML, Blocks, Django, Handlebars, Pug, Jet
andAce
) withembed.FS
orfs.FS
(in addition tostring
andhttp.FileSystem
types). -
Add support for
embed.FS
andfs.FS
onapp.HandleDir
. -
Add
iris.Patches()
package-level function to customize Iris Request Context REST (and more to come) behavior. -
Minor fixes.
-
Enable setting a custom "go-redis" client through
SetClient
go redis driver method orClient
struct field on sessions/database/redis driver as requested at chat. -
Ignore
"csrf.token"
form data key when missing onctx.ReadForm
by default as requested at #1941. -
Fix CVE-2020-5398.
-
New
{x:weekday}
path parameter type, example code:
// 0 to 7 (leading zeros don't matter) or "Sunday" to "Monday" or "sunday" to "monday".
// http://localhost:8080/schedule/monday or http://localhost:8080/schedule/Monday or
// http://localhost:8080/schedule/1 or http://localhost:8080/schedule/0001.
app.Get("/schedule/{day:weekday}", func(ctx iris.Context) {
day, _ := ctx.Params().GetWeekday("day")
ctx.Writef("Weekday requested was: %v\n", day)
})
-
Make the
Context.JSON
method customizable by modifying thecontext.WriteJSON
package-level function. -
Add new
iris.NewGuide
which helps you build a simple and nice JSON API with services as dependencies and better design pattern. -
Make
Context.Domain()
customizable by letting developers to modify theContext.GetDomain
package-level function. -
Remove Request Context-based Transaction feature as its usage can be replaced with just the Iris Context (as of go1.7+) and better project structure.
-
Fix #1882
-
Fix #1877
-
Fix #1876
-
New
date
dynamic path parameter type. E.g./blog/{param:date}
matches to"/blog/2022/04/21"
. -
Add
iris.AllowQuerySemicolons
andiris.WithoutServerError(iris.ErrURLQuerySemicolon)
to handle golang.org/issue/25192 as reported at: #1875. -
Add new
Application.SetContextErrorHandler
to globally customize the default behavior (status code 500 without body) onJSON
,JSONP
,Protobuf
,MsgPack
,XML
,YAML
andMarkdown
method call write errors instead of catching the error on each handler. -
Add new x/pagination sub-package which supports generics code (go 1.18+).
-
Add new middleware/modrevision middleware (example at [_examples/project/api/router.go]_examples/project/api/router.go).
-
Add
iris.BuildRevision
andiris.BuildTime
to embrace the new go's 1.18 debug build information. -
Addupdate: remains as it's, per JSON call.Context.SetJSONOptions
to customize on a higher level the JSON options onContext.JSON
calls. -
Add new auth sub-package which helps on any user type auth using JWT (access & refresh tokens) and a cookie (optional).
-
Add
Party.EnsureStaticBindings
which, if called, the MVC binder panics if a struct's input binding depends on the HTTP request data instead of a static dependency. This is useful to make sure your API crafted throughParty.PartyConfigure
depends only on struct values you already defined atParty.RegisterDependency
== will never use reflection at serve-time (maximum performance). -
Add a new x/reflex sub-package.
-
Add
Context.ReadMultipartRelated
as requested at: issues/#1787. -
Add
Container.DependencyMatcher
andDependency.Match
to implement the feature requested at issues/#1842. -
Register CORS middleware to the Application by default when
iris.Default()
is used instead ofiris.New()
. -
Add x/jsonx: DayTime for JSON marshal and unmarshal of "15:04:05" (hour, minute, second).
-
Fix a bug of
WithoutBodyConsumptionOnUnmarshal
configurator and a minor dependency injection issue caused by the previous alpha version between 20 and 26 February of 2022. -
New basic cors middleware.
-
New
httptest.NewServer
helper. -
New x/errors sub-package, helps with HTTP Wire Errors. Example can be found here.
-
New x/timex sub-package, helps working with weekdays.
-
Minor improvements to the JSON Kitchen Time.
-
A session database can now implement the
EndRequest(ctx *context.Context, session *Session)
method which will be fired at the end of the request-response lifecycle. -
Improvements on JSON and ReadJSON when
Iris.Configuration.EnableOptimizations
is true. The request's Context is used whenever is necessary. -
New monitor middleware.
-
New
RegisterRequestHandler
package-level and client methods to the newx/client
package. Control or log the request-response lifecycle. -
New
RateLimit
andDebug
HTTP Client options to the newx/client
package. -
Push a security fix reported by Kirill Efimov for older go runtimes.
-
New
Configuration.Timeout
andConfiguration.TimeoutMessage
fields. Use it to set HTTP timeouts. Note that your http server's (Application.ConfigureHost
) Read/Write timeouts should be a bit higher than theConfiguration.Timeout
in order to give some time to http timeout handler to kick in and be able to send theConfiguration.TimeoutMessage
properly. -
New
apps.OnApplicationRegistered
method which listens on new Iris applications hosted under the same binary. Use it on yourinit
functions to configure Iris applications by any spot in your project's files. -
Context.JSON
respects any object implements theeasyjson.Marshaler
interface and renders the result using the easyjon's writer. Set theConfiguration.EnableProtoJSON
andConfiguration.EnableEasyJSON
to true in order to enable this feature. -
minor:
Context
structure implements the standard go Context interface now (includes: Deadline, Done, Err and Value methods). Handlers can now just pass thectx iris.Context
as a shortcut ofctx.Request().Context()
when needed. -
New x/jsonx sub-package for JSON type helpers.
-
New x/mathx sub-package for math related functions.
-
New /x/client HTTP Client sub-package.
-
New
email
builtin path parameter type. Example:
// +------------------------+
// | {param:email} |
// +------------------------+
// Email + mx look up path parameter validation. Use it on production.
// http://localhost:8080/user/kataras2006@hotmail.com -> OK
// http://localhost:8080/user/b-c@invalid_domain -> NOT FOUND
app.Get("/user/{user_email:email}", func(ctx iris.Context) {
email := ctx.Params().Get("user_email")
ctx.WriteString(email)
})
// +------------------------+
// | {param:mail} |
// +------------------------+
// Simple email path parameter validation.
// http://localhost:8080/user/kataras2006@hotmail.com -> OK
// http://localhost:8080/user/b-c@invalid_domainxxx1.com -> NOT FOUND
app.Get("/user/{local_email:mail}", func(ctx iris.Context) {
email := ctx.Params().Get("local_email")
ctx.WriteString(email)
})
- New
iris.IsErrEmptyJSON(err) bool
which reports whether the given "err" is caused by aContext.ReadJSON
call when the request body didn't start with { (or it was totally empty).
Example Code:
func handler(ctx iris.Context) {
var opts SearchOptions
if err := ctx.ReadJSON(&opts); err != nil && !iris.IsErrEmptyJSON(err) {
ctx.StopWithJSON(iris.StatusBadRequest, iris.Map{"message": "unable to parse body"})
return
}
// [...continue with default values of "opts" struct if the client didn't provide some]
}
That means that the client can optionally set a JSON body.
-
New
APIContainer.EnableStrictMode(bool)
to disable automatic payload binding and panic on missing dependencies for exported struct'sfields or function's input parameters on MVC controller or hero function or PartyConfigurator. -
New
Party.PartyConfigure(relativePath string, partyReg ...PartyConfigurator) Party
helper, registers a children Party likeParty
andPartyFunc
but instead it accepts a structure value which may contain one or more of the dependencies registered byRegisterDependency
orConfigureContainer().RegisterDependency
methods and fills the unset/zero exported struct's fields respectfully (useful when the api's dependencies amount are too much to pass on a function). -
New feature: add the ability to set custom error handlers on path type parameters errors (existing or custom ones). Example Code:
app.Macros().Get("uuid").HandleError(func(ctx iris.Context, paramIndex int, err error) {
ctx.StatusCode(iris.StatusBadRequest)
param := ctx.Params().GetEntryAt(paramIndex)
ctx.JSON(iris.Map{
"error": err.Error(),
"message": "invalid path parameter",
"parameter": param.Key,
"value": param.ValueRaw,
})
})
app.Get("/users/{id:uuid}", getUser)
-
Improve the performance and fix
:int, :int8, :int16, :int32, :int64, :uint, :uint8, :uint16, :uint32, :uint64
path type parameters couldn't accept a positive number written with the plus symbol or with a leading zeroes, e.g.+42
and021
. -
The
iris.WithEmptyFormError
option is respected oncontext.ReadQuery
method too, as requested at #1727. Example comments were updated. -
New
httptest.Strict
option setter to enable thehttpexpect.RequireReporter
instead of the default `httpexpect.AssetReporter. Use that to enable complete test failure on the first error. As requested at: #1722. -
New
uuid
builtin path parameter type. Example:
// +------------------------+
// | {param:uuid} |
// +------------------------+
// UUIDv4 (and v1) path parameter validation.
// http://localhost:8080/user/bb4f33e4-dc08-40d8-9f2b-e8b2bb615c0e -> OK
// http://localhost:8080/user/dsadsa-invalid-uuid -> NOT FOUND
app.Get("/user/{id:uuid}", func(ctx iris.Context) {
id := ctx.Params().Get("id")
ctx.WriteString(id)
})
-
New
Configuration.KeepAlive
andiris.WithKeepAlive(time.Duration) Configurator
added as helpers to start the server using a tcp listener featured with keep-alive. -
New
DirOptions.ShowHidden bool
is added by @tuhao1020 at PR #1717 to show or hide the hidden files whenShowList
is set to true. -
New
Context.ReadJSONStream
method andJSONReader
options forContext.ReadJSON
andContext.ReadJSONStream
, see the example. -
New
FallbackView
feature, per-party or per handler chain. Example can be found at: _examples/view/fallback.
app.FallbackView(iris.FallbackViewFunc(func(ctx iris.Context, err iris.ErrViewNotExist) error {
// err.Name is the previous template name.
// err.IsLayout reports whether the failure came from the layout template.
// err.Data is the template data provided to the previous View call.
// [...custom logic e.g. ctx.View("fallback.html", err.Data)]
return err
}))
- New
versioning.Aliases
middleware and up to 80% faster version resolve. Example Code:
app := iris.New()
api := app.Party("/api")
api.Use(Aliases(map[string]string{
versioning.Empty: "1", // when no version was provided by the client.
"beta": "4.0.0",
"stage": "5.0.0-alpha"
}))
v1 := NewGroup(api, ">=1.0.0 <2.0.0")
v1.Get/Post...
v4 := NewGroup(api, ">=4.0.0 <5.0.0")
v4.Get/Post...
stage := NewGroup(api, "5.0.0-alpha")
stage.Get/Post...
-
New Basic Authentication middleware. Its
Default
function has not changed, however, the rest, e.g.New
contains breaking changes as the new middleware features new functionalities. -
Add
iris.DirOptions.SPA bool
field to allow Single Page Applications under a file server. -
A generic User interface, see the
Context.SetUser/User
methods in the New Context Methods section for more. In-short, the basicauth middleware's stored user can now be retrieved throughContext.User()
which provides more information than the nativectx.Request().BasicAuth()
method one. Third-party authentication middleware creators can benefit of these two methods, plus the Logout below. -
A
Context.Logout
method is added, can be used to invalidate basicauth or jwt client credentials. -
Add the ability to share functions between handlers chain and add an example on sharing Go structures (aka services).
-
Add the new
Party.UseOnce
method to the*Route
-
Add a new
*Route.RemoveHandler(...interface{}) int
andParty.RemoveHandler(...interface{}) Party
methods, delete a handler based on its name or the handler pc function.
func middleware(ctx iris.Context) {
// [...]
}
func main() {
app := iris.New()
// Register the middleware to all matched routes.
app.Use(middleware)
// Handlers = middleware, other
app.Get("/", index)
// Handlers = other
app.Get("/other", other).RemoveHandler(middleware)
}
-
Redis Driver is now based on the go-redis module. Radix and redigo removed entirely. Sessions are now stored in hashes which fixes issue #1610. The only breaking change on default configuration is that the
redis.Config.Delim
option was removed. The redis sessions database driver is now defaults to the&redis.GoRedisDriver{}
. End-developers can implement their own implementations too. TheDatabase#Close
is now automatically called on interrupt signals, no need to register it by yourself. -
Add builtin support for i18n pluralization. Please check out the following yaml locale example to see an overview of the supported formats.
-
Fix #1650
-
Fix #1649
-
Fix #1648
-
Fix #1641
-
Add
Party.SetRoutesNoLog(disable bool) Party
to disable (the new) verbose logging of next routes. -
Add
mvc.Application.SetControllersNoLog(disable bool) *mvc.Application
to disable (the new) verbose logging of next controllers. As requested at #1630. -
Fix #1621 and add a new
cache.WithKey
to customize the cached entry key. -
Add a
Response() *http.Response
to the Response Recorder. -
Fix Response Recorder
Flush
when transfer-encoding ischunked
. -
Fix Response Recorder
Clone
concurrent access afterwards. -
Add a
ParseTemplate
method on view engines to manually parse and add a template from a text as requested. Examples. -
Full
http.FileSystem
interface support for all view engines as requested. The first argument of the functions(HTML
,Blocks
,Pug
,Ace
,Jet
,Django
,Handlebars
) can now be either a directory ofstring
type (like before) or a value which completes thehttp.FileSystem
interface. The.Binary
method of all view engines was removed: pass the go-bindata's latest versionAssetFile()
exported function as the first argument instead of string. -
Add
Route.ExcludeSitemap() *Route
to exclude a route from sitemap as requested in chat, also offline routes are excluded automatically now. -
Improved tracing (with
app.Logger().SetLevel("debug")
) for routes. Screens:
-
Update the pprof middleware.
-
New
Controller.HandleHTTPError(mvc.Code) <T>
optional Controller method to handle http errors as requested at: MVC - More Elegent OnErrorCode registration?. Example can be found here.
- New Rewrite Engine Middleware. Set up redirection rules for path patterns using the syntax we all know. Example Code.
RedirectMatch: # REDIRECT_CODE_DIGITS | PATTERN_REGEX | TARGET_REPL
# Redirects /seo/* to /*
- 301 /seo/(.*) /$1
# Redirects /docs/v12* to /docs
- 301 /docs/v12(.*) /docs
# Redirects /old(.*) to /
- 301 /old(.*) /
# Redirects http or https://test.* to http or https://newtest.*
- 301 ^(http|https)://test.(.*) $1://newtest.$2
# Handles /*.json or .xml as *?format=json or xml,
# without redirect. See /users route.
# When Code is 0 then it does not redirect the request,
# instead it changes the request URL
# and leaves a route handle the request.
- 0 /(.*).(json|xml) /$1?format=$2
# Redirects root domain to www.
# Creation of a www subdomain inside the Application is unnecessary,
# all requests are handled by the root Application itself.
PrimarySubdomain: www
- New
TraceRoute bool
on middleware/logger middleware. Displays information about the executed route. Also marks the handlers executed. Screenshot:
-
Implement feature request Log when I18n Translation Fails? by using the new
Application.I18n.DefaultMessageFunc
field beforeI18n.Load
. Example of usage. -
Fix #1594 and add a new
PathAfterHandler
which can be set to true to enable the old behavior (not recommended though). -
New apps subpackage. Example of usage.
- Fix
AutoTLS
when used withiris.TLSNoRedirect
*. TheAutoTLS
runner can be customized through the newiris.AutoTLSNoRedirect
instead, read its go documentation. Example of having both TLS and non-TLS versions of the same application without conflicts with letsencrypt./well-known
path:
package main
import (
"net/http"
"time"
"github.com/kataras/iris/v12"
)
func main() {
app := iris.New()
app.Logger().SetLevel("debug")
app.Get("/", func(ctx iris.Context) {
ctx.JSON(iris.Map{
"time": time.Now().Unix(),
"tls": ctx.Request().TLS != nil,
})
})
var fallbackServer = func(acme func(http.Handler) http.Handler) *http.Server {
srv := &http.Server{Handler: acme(app)}
go srv.ListenAndServe()
return srv
}
app.Run(iris.AutoTLS(":443", "example.com", "mail@example.com",
iris.AutoTLSNoRedirect(fallbackServer)))
}
-
iris.Minify
middleware to minify responses based on their media/content-type. -
Context.OnCloseErr
andContext.OnConnectionCloseErr
- to call a function offunc() error
instead of aniris.Handler
when request is closed or manually canceled. -
Party.UseError(...Handler)
- to register handlers to run before any http errors (e.g. beforeOnErrorCode/OnAnyErrorCode
or default error codes when no handler is responsible to handle a specific http status code). -
Party.UseRouter(...Handler) and Party.ResetRouterFilters()
- to register handlers before the main router, useful on handlers that should control whether the router itself should ran or not. Independently of the incoming request's method and path values. These handlers will be executed ALWAYS against ALL incoming matched requests. Example of use-case: CORS. -
*versioning.Group
type is a fullParty
now. -
Party.UseOnce
- either inserts a middleware, or on the basis of the middleware already existing, replace that existing middleware instead. -
Ability to register a view engine per group of routes or for the current chain of handlers through
Party.RegisterView
andContext.ViewEngine
respectfully. -
Add Blocks template engine.
-
Add Ace template parser to the view engine and other minor improvements.
-
Fix huge repo size of 55.7MB, which slows down the overall Iris installation experience. Now, go-get performs ~3 times faster. I 've managed it using the bfg-repo-cleaner tool - an alternative to git-filter-branch command. Watch the small gif below to learn how:
-
gRPC features:
- New Router Wrapper.
- New MVC
.Handle(ctrl, mvc.GRPC{...})
option which allows to register gRPC services per-party (without the requirement of a full wrapper) and optionally strict access to gRPC clients only, see the example here.
-
Add
Configuration.RemoteAddrHeadersForce bool
to forceContext.RemoteAddr() string
to return the first entry of request headers as a fallback instead of theRequest.RemoteAddr
one, as requested at: 1567#issuecomment-663972620. -
Fix #1564.
-
Fix #1553.
-
New
DirOptions.Cache
to cache assets in-memory among with their compressed contents (in order to be ready to served if client ask). Learn more about this feature by reading all #1556 comments. Usage:
var dirOpts = DirOptions{
// [...other options]
Cache: DirCacheOptions{
Enable: true,
// Don't compress files smaller than 300 bytes.
CompressMinSize: 300,
// Ignore compress already compressed file types
// (some images and pdf).
CompressIgnore: iris.MatchImagesAssets,
// Gzip, deflate, br(brotli), snappy.
Encodings: []string{"gzip", "deflate", "br", "snappy"},
// Log to the stdout the total reduced file size.
Verbose: 1,
},
}
- New
DirOptions.PushTargets
andPushTargetsRegexp
to push index' assets to the client without additional requests. Inspirated by issue #1562. Example matching all.js, .css and .ico
files (recursively):
var dirOpts = iris.DirOptions{
// [...other options]
IndexName: "/index.html",
PushTargetsRegexp: map[string]*regexp.Regexp{
"/": regexp.MustCompile("((.*).js|(.*).css|(.*).ico)$"),
// OR:
// "/": iris.MatchCommonAssets,
},
Compress: true,
}
-
Update jet parser to v5.0.2, closes #1551. It contains two breaking changes by its author:
- Relative paths on
extends, import, include...
tmpl functions, e.g.{{extends "../layouts/application.jet"}}
instead oflayouts/application.jet
- the new jet.Ranger interface now requires a
ProvidesIndex() bool
method too - Example has been updated
- Relative paths on
-
Fix #1552.
-
Proper listing of root directories on
Party.HandleDir
when itsDirOptions.ShowList
was set to true.- Customize the file/directory listing page through views, see example.
-
Socket Sharding as requested at #1544. New
iris.WithSocketSharding
Configurator andSocketSharding bool
setting. -
Versioned Controllers feature through the new
mvc.Version
option. See _examples/mvc/versioned-controller. -
Fix #1539.
-
New rollbar example.
-
New builtin requestid middleware.
-
New builtin JWT middleware based on the fastest JWT implementation; kataras/jwt featured with optional wire encryption to set claims with sensitive data when necessary.
-
New
iris.RouteOverlap
route registration rule.Party.SetRegisterRule(iris.RouteOverlap)
to allow overlapping across multiple routes for the same request subdomain, method, path. See 1536#issuecomment-643719922. This allows two or more MVC Controllers to listen on the same path based on one or more registered dependencies (see _examples/mvc/authenticated-controller). -
Context.ReadForm
now can return aniris.ErrEmptyForm
instead ofnil
when the newConfiguration.FireEmptyFormError
is true (wheniris.WithEmptyFormError
is set) on missing form body to read from. -
Configuration.EnablePathIntelligence | iris.WithPathIntelligence
to enable path intelligence automatic path redirection on the most closest path (if any), [example]((https://github.com/kataras/iris/blob/main/_examples/routing/intelligence/main.go) -
Enhanced cookie security and management through new
Context.AddCookieOptions
method and new cookie options (look on New Package-level functions section below), securecookie example has been updated. -
Context.RemoveCookie
removes also the Request's specific cookie of the same request lifecycle wheniris.CookieAllowReclaim
is set to cookie options, example. -
iris.TLS
can now accept certificates in form of raw[]byte
contents too. -
iris.TLS
registers a secondary http server which redirects "http://" to their "https://" equivalent requests, unless the newiris.TLSNoRedirect
host Configurator is provided oniris.TLS
, e.g.app.Run(iris.TLS("127.0.0.1:443", "mycert.cert", "mykey.key", iris.TLSNoRedirect))
. There isiris.AutoTLSNoRedirect
option forAutoTLS
too. -
Fix an issue about i18n loading from path which contains potential language code.
-
Server will not return neither log the
ErrServerClosed
error ifapp.Shutdown
was called manually via interrupt signal(CTRL/CMD+C), note that if the server closed by any other reason the error will be fired as previously (unlessiris.WithoutServerError(iris.ErrServerClosed)
). -
Finally, Log level's and Route debug information colorization is respected across outputs. Previously if the application used more than one output destination (e.g. a file through
app.Logger().AddOutput
) the color support was automatically disabled from all, including the terminal one, this problem is fixed now. Developers can now see colors in their terminals while log files are kept with clear text. -
New
iris.WithLowercaseRouting
option which forces all routes' paths to be lowercase and converts request paths to their lowercase for matching. -
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" "
(four spaces) and" "
respectfully otherwise it is empty or the provided value. -
Hero Handlers (and
app.ConfigureContainer().Handle
) do not have to requireiris.Context
just to callctx.Next()
anymore, this is done automatically now. -
Improve Remote Address parsing as requested at: #1453. Add
Configuration.RemoteAddrPrivateSubnets
to exclude those addresses when fetched byConfiguration.RemoteAddrHeaders
throughcontext.RemoteAddr() string
. -
Fix #1487.
-
Fix #1473.
iris.DirListRichOptions
to pass oniris.DirListRich
method.iris.DirListRich
to override the default look and feel if theDirOptions.ShowList
was set to true, can be passed toDirOptions.DirList
field.DirOptions.PushTargets
for http/2 push on index *.iris.Compression
middleware to compress responses and decode compressed request data respectfully.iris.B, KB, MB, GB, TB, PB, EB
for byte units.TLSNoRedirect
to disable automatic "http://" to "https://" redirections (see below)CookieAllowReclaim
,CookieAllowSubdomains
,CookieSameSite
,CookieSecure
andCookieEncoding
to bring previously sessions-only features to all cookies in the request.
Context.FormFiles(key string, before ...func(*Context, *multipart.FileHeader) bool) (files []multipart.File, headers []*multipart.FileHeader, err error)
method.Context.ReadURL(ptr interface{}) error
shortcut ofReadParams
andReadQuery
. Binds URL dynamic path parameters and URL query parameters to the given "ptr" pointer of a struct value.Context.SetUser(User)
andContext.User() User
to store and retrieve an authenticated client. Read more here.Context.SetLogoutFunc(fn interface{}, persistenceArgs ...interface{})
andLogout(args ...interface{}) error
methods to allow different kind of auth middlewares to be able to set a "logout" a user/client feature with a single function, the route handler may not be aware of the implementation of the authentication used.Context.SetFunc(name string, fn interface{}, persistenceArgs ...interface{})
andContext.CallFunc(name string, args ...interface{}) ([]reflect.Value, error)
to allow middlewares to share functions dynamically when the type of the function is not predictable, see the example for more.Context.TextYAML(interface{}) error
same asContext.YAML
but with set the Content-Type totext/yaml
instead (Google Chrome renders it as text).Context.IsDebug() bool
reports whether the application is running under debug/development mode. It is a shortcut of Application.Logger().Level >= golog.DebugLevel.Context.IsRecovered() bool
reports whether the current request was recovered from the recover middleware. Also theContext.GetErrPublic() (bool, error)
,Context.SetErrPrivate(err error)
methods andiris.ErrPrivate
interface have been introduced.Context.RecordRequestBody(bool)
same as the Application'sDisableBodyConsumptionOnUnmarshal
configuration field but registers per chain of handlers. It makes the request body readable more than once.Context.IsRecordingBody() bool
reports whether the request body can be readen multiple times.Context.ReadHeaders(ptr interface{}) error
binds request headers to "ptr". Example.Context.ReadParams(ptr interface{}) error
binds dynamic path parameters to "ptr". Example.Context.SaveFormFile(fh *multipart.FileHeader, dest string) (int64, error)
previously unexported. Accepts a result file ofContext.FormFile
and saves it to the disk.Context.URLParamSlice(name string) []string
is a a shortcut ofctx.Request().URL.Query()[name]
. LikeURLParam
but it returns all values as a string slice instead of a single string separated by commas. Note that it skips any empty values (e.g. https://iris-go.com?values=).Context.PostValueMany(name string) (string, error)
returns the post data of a given key. The returned value is a single string separated by commas on multiple values. It also reports whether the form was empty or when the "name" does not exist or whether the available values are empty. It strips any empty key-values from the slice before return. SeeErrEmptyForm
,ErrNotFound
andErrEmptyFormField
respectfully. ThePostValueInt
,PostValueInt64
,PostValueFloat64
andPostValueBool
now respect the above errors too (thePostValues
method now returns a second output argument oferror
too, see breaking changes below).Context.URLParamsSorted() []memstore.StringEntry
returns a sorted (by key) slice of key-value entries of the URL Query parameters.Context.ViewEngine(ViewEngine)
to set a view engine on-fly for the current chain of handlers, responsible to render templates throughctx.View
. Example.Context.SetErr(error)
andContext.GetErr() error
helpers.Context.CompressWriter(bool) error
andContext.CompressReader(bool) error
.Context.Clone() Context
returns a copy of the Context safe for concurrent access.Context.IsCanceled() bool
reports whether the request has been canceled by the client.Context.IsSSL() bool
reports whether the request is under HTTPS SSL (NewConfiguration.SSLProxyHeaders
andHostProxyHeaders
fields too).Context.CompressReader(enable bool)
method andiris.CompressReader
middleware to enable future request read body calls to decompress data, example.Context.RegisterDependency(v interface{})
andContext.UnregisterDependency(typ reflect.Type)
to register/remove struct dependencies on serve-time through a middleware.Context.SetID(id interface{})
andContext.GetID() interface{}
added to register a custom unique indetifier to the Context, if necessary.Context.Scheme() string
returns the full scheme of the request URL.Context.SubdomainFull() string
returns the full subdomain(s) part of the host (host[0:rootLevelDomain]
).Context.Domain() string
returns the root level domain.Context.AddCookieOptions(...CookieOption)
adds options forSetCookie
,SetCookieKV, UpsertCookie
andRemoveCookie
methods for the current request.Context.ClearCookieOptions()
clears any cookie options registered throughAddCookieOptions
.Context.SetLanguage(langCode string)
force-sets a language code from inside a middleare, similar to theapp.I18n.ExtractFunc
Context.ServeContentWithRate
,ServeFileWithRate
andSendFileWithRate
methods to throttle the "download" speed of the clientContext.IsHTTP2() bool
reports whether the protocol version for incoming request was HTTP/2Context.IsGRPC() bool
reports whether the request came from a gRPC clientContext.UpsertCookie(*http.Cookie, cookieOptions ...context.CookieOption)
upserts a cookie, fixes #1485 tooContext.StopWithStatus(int)
stops the handlers chain and writes the status codeStopWithText(statusCode int, format string, args ...interface{})
stops the handlers chain, writes thre status code and a plain text messageContext.StopWithError(int, error)
stops the handlers chain, writes thre status code and the error's messageContext.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 client (note that theContext.JSON
is able to send protobuf as JSON)Context.MsgPack(interface{})
sends msgpack format data to the clientContext.ReadProtobuf(ptr)
binds request body to a proto messageContext.ReadJSONProtobuf(ptr, ...options)
binds JSON 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.ReflectValue() []reflect.Value
stores and returns the[]reflect.ValueOf(ctx)
Context.Controller() reflect.Value
returns the current MVC Controller value.
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.ConfigureContainer(builder ...func(*iris.APIContainer)) *APIContainer
method which returns methods such as Handle(method, relativePath string, handlersFn ...interface{}) *Route
and 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.ConfigureContainer(func(api *iris.APIContainer) {
api.Post("/{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. Here is a quick list of the new Party.ConfigureContainer()'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(iris.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)
//
// 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{})
// UseResultHandler adds a result handler to the Container.
// A result handler can be used to inject the returned struct value
// from a request handler or to replace the default renderer.
UseResultHandler(handler func(next iris.ResultHandler) iris.ResultHandler)
ResultHandler
type ResultHandler func(ctx iris.Context, v interface{}) error
// 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
// Get registers a GET route, same as `Handle("GET", relativePath, handlersFn....)`.
Get(relativePath string, handlersFn ...interface{}) *Route
// and so on...
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 |
---|---|
*mvc.Application | Current MVC Application |
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() |
*golog.Logger | Iris Logger |
net.IP | net.ParseIP(ctx.RemoteAddr()) |
mvc.Code | ctx.GetStatusCode() int |
mvc.Err | ctx.GetErr() error |
iris/context.User | ctx.User() |
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:
1. Declare Go types for client's request body and a server's response.
type (
request struct {
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
}
response struct {
ID uint64 `json:"id"`
Message string `json:"message"`
}
)
2. Create the route handler.
Path parameters and request body are binded automatically.
- id uint64 binds to "id:uint64"
- input request binds to client request data such as JSON
func updateUser(id uint64, input request) response {
return response{
ID: id,
Message: "User updated successfully",
}
}
3. Configure the container per group and register the route.
app.Party("/user").ConfigureContainer(container)
func container(api *iris.APIContainer) {
api.Put("/{id:uint64}", updateUser)
}
4. Simulate a client request which sends data to the server and displays the response.
curl --request PUT -d '{"firstanme":"John","lastname":"Doe"}' http://localhost:8080/user/42
{
"id": 42,
"message": "User updated successfully"
}
Before we continue to the next section, register dependencies, you may want to learn how a response can be customized through the iris.Context
right before sent to the client.
The server will automatically execute the Preflight(iris.Context) error
method of a function's output struct value right before send the response to the client.
Take for example that you want to fire different HTTP status codes depending on the custom logic inside your handler and also modify the value(response body) itself before sent to the client. Your response type should contain a Preflight
method like below.
type response struct {
ID uint64 `json:"id,omitempty"`
Message string `json:"message"`
Code int `json:"code"`
Timestamp int64 `json:"timestamp,omitempty"`
}
func (r *response) Preflight(ctx iris.Context) error {
if r.ID > 0 {
r.Timestamp = time.Now().Unix()
}
if r.Code > 0 {
ctx.StatusCode(r.Code)
}
return nil
}
Now, each handler that returns a *response
value will call the response.Preflight
method automatically.
func deleteUser(db *sql.DB, id uint64) *response {
// [...custom logic]
return &response{
Message: "User has been marked for deletion",
Code: iris.StatusAccepted,
}
}
If you register the route and fire a request you should see an output like this, the timestamp is filled and the HTTP status code of the response that the client will receive is 202 (Status Accepted).
{
"message": "User has been marked for deletion",
"code": 202,
"timestamp": 1583313026
}
1. Import packages to interact with a database. The go-sqlite3 package is a database driver for SQLite.
import "database/sql"
import _ "github.com/mattn/go-sqlite3"
2. Configure the container (see above), register your dependencies. Handler expects an *sql.DB instance.
localDB, _ := sql.Open("sqlite3", "./foo.db")
api.RegisterDependency(localDB)
3. Register a route to create a user.
api.Post("/{id:uint64}", createUser)
4. The create user Handler.
The handler accepts a database and some client request data such as JSON, Protobuf, Form, URL Query and e.t.c. It Returns a response.
func createUser(db *sql.DB, user request) *response {
// [custom logic using the db]
userID, err := db.CreateUser(user)
if err != nil {
return &response{
Message: err.Error(),
Code: iris.StatusInternalServerError,
}
}
return &response{
ID: userID,
Message: "User created",
Code: iris.StatusCreated,
}
}
5. Simulate a client to create a user.
# JSON
curl --request POST -d '{"firstname":"John","lastname":"Doe"}' \
--header 'Content-Type: application/json' \
http://localhost:8080/user
# Form (multipart)
curl --request POST 'http://localhost:8080/users' \
--header 'Content-Type: multipart/form-data' \
--form 'firstname=John' \
--form 'lastname=Doe'
# Form (URL-encoded)
curl --request POST 'http://localhost:8080/users' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'firstname=John' \
--data-urlencode 'lastname=Doe'
# URL Query
curl --request POST 'http://localhost:8080/users?firstname=John&lastname=Doe'
Response:
{
"id": 42,
"message": "User created",
"code": 201,
"timestamp": 1583313026
}
- The
versioning.NewMatcher
has been removed entirely in favor ofNewGroup
. Strict versions format onversioning.NewGroup
is required. E.g."1"
is not valid anymore, you have to specify"1.0.0"
. Example:NewGroup(api, ">=1.0.0 <2.0.0")
. The routing/versioning examples have been updated. - Now that
RegisterView
can be used to register different view engines per-Party, there is no need to support registering multiple engines under the same Party. Theapp.RegisterView
now upserts the given Engine instead of append. You can now render templates without file extension, e.g.index
instead ofindex.ace
, both forms are valid now. - The
Context.ContentType
does not accept filenames to resolve the mime type anymore (caused issues with vendor-specific(vnd) MIME types). - The
Configuration.RemoteAddrPrivateSubnets.IPRange.Start and End
are now type ofstring
instead ofnet.IP
. TheWithRemoteAddrPrivateSubnet
option remains as it is, already acceptsstring
s. - The
i18n#LoaderConfig.FuncMap template.FuncMap
field was replaced withFuncs func(iris.Locale) template.FuncMap
in order to give current locale access to the template functions. A newapp.I18n.Loader
was introduced too, in order to make it easier for end-developers to customize the translation key values. - Request Logger's
Columns bool
field has been removed. Use the new accesslog middleware instead. - The
.Binary
method of all view engines was removed: pass the go-bindata's latest versionAssetFile()
exported function as the first argument instead of string. All examples updated. ContextUploadFormFiles(destDirectory string, before ...func(*Context, *multipart.FileHeader) bool) (uploaded []*multipart.FileHeader, n int64, err error)
now returns the total files uploaded too (as its first parameter) and the "before" variadic option should return a boolean, if false then the specific file is skipped.Context.PostValues(name string) ([]string, error)
now returns a second output argument oferror
type too, which reportsErrEmptyForm
orErrNotFound
orErrEmptyFormField
. The single post value getters now returns the last value if multiple was given instead of the first one (this allows clients to append values on flow updates).Party.GetReporter()
removed. TheApplication.Build
returns the first error now and the API's errors are logged, this allows the server to run even if some of the routes are invalid but not fatal to the entire application (it was a request from a company).versioning.NewGroup(string)
now accepts aParty
as its first input argument:NewGroup(Party, string)
.versioning.RegisterGroups
is removed as it is no longer necessary.Configuration.RemoteAddrHeaders
frommap[string]bool
to[]string
. If you usedWith(out)RemoteAddrHeader
then you are ready to proceed without any code changes for that one.ctx.Gzip(boolean)
replaced withctx.CompressWriter(boolean) error
.ctx.GzipReader(boolean) error
replaced withctx.CompressReader(boolean) error
.iris.Gzip
andiris.GzipReader
replaced withiris.Compression
(middleware).ctx.ClientSupportsGzip() bool
replaced withctx.ClientSupportsEncoding("gzip", "br" ...) bool
.ctx.GzipResponseWriter()
is removed.Party.HandleDir/iris.FileServer
now accepts bothhttp.FileSystem
andstring
and returns a list of[]*Route
(GET and HEAD) instead of GET only. You can write: bothapp.HandleDir("/", iris.Dir("./assets"))
andapp.HandleDir("/", "./assets")
andDirOptions.Asset, AssetNames, AssetInfo
removed, usego-bindata -fs [..]
andapp.HandleDir("/", AssetFile())
instead.Context.OnClose
andContext.OnCloseConnection
now both accept aniris.Handler
instead of a simplefunc()
as their callback.Context.StreamWriter(writer func(w io.Writer) bool)
changed toStreamWriter(writer func(w io.Writer) error) error
and it's now theContext.Request().Context().Done()
channel that is used to receive any close connection/manual cancel signals, instead of the deprecatedResponseWriter().CloseNotify()
one. Same for theContext.OnClose
andContext.OnCloseConnection
methods.- Fixed handler's error response not be respected when response recorder was used instead of the common writer. Fixes #1531. It contains a BREAKING CHANGE of: the new
Configuration.ResetOnFireErrorCode
field should be set to true in order to behave as it used before this update (to reset the contents on recorder). Context.String()
(rarely used by end-developers) it does not return a unique string anymore, to achieve the old representation you must call the newContext.SetID
method first.iris.CookieEncode
andCookieDecode
are replaced with theiris.CookieEncoding
.sessions#Config.Encode
andDecode
are removed in favor of (the existing)Encoding
field.versioning.GetVersion
now returns an empty string if version wasn't found.- Change the MIME type of
Javascript .js
andJSONP
as the HTML specification now recommends to"text/javascript"
instead of the obselete"application/javascript"
. This change was pushed to theGo
language itself as well. See https://go-review.googlesource.com/c/go/+/186927/. - Remove the last input argument of
enableGzipCompression
inContext.ServeContent
,ServeFile
methods. This was deprecated a few versions ago. A middleware (app.Use(iris.CompressWriter)
) or a prior call toContext.CompressWriter(true)
will enable compression. Also these two methods andContext.SendFile
one now supportContent-Range
andAccept-Ranges
correctly out of the box (net/http
had a bug, which is now fixed). Context.ServeContent
no longer returns an error, seeServeContentWithRate
,ServeFileWithRate
andSendFileWithRate
new methods too.route.Trace() string
changed toroute.Trace(w io.Writer)
, to achieve the same result just pass abytes.Buffer
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- REMOVE the
kataras/iris/v12/typescript
package in favor of the new iris-cli. Also, the alm typescript online editor was removed as it is deprecated by its author, please consider using the designtsx instead.
New Features:
Fixes:
New Examples:
Implement new SetRegisterRule(iris.RouteOverride, RouteSkip, RouteError)
to resolve: #1448
New Examples:
Fixes:
Various improvements and linting.
Minor fix on serving embedded files.
Fix [BUG] [iris.Default] RegisterView
Fix [BUG]Session works incorrectly when meets the multi-level TLDs.
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>")
}
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
.
All known issues.
Support for i18n is now a builtin feature and is being respected across your entire application, per say sitemap and views.
Iris generates and serves one or more sitemap.xml for your static routes.
Navigate through: https://github.com/kataras/iris/blob/main/_examples/routing/sitemap/main.go for more.
- _examples/i18n
- _examples/sitemap
- _examples/desktop/blink
- _examples/desktop/lorca
- _examples/desktop/webview
- 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.
- 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
This minor version contains improvements on the Problem Details for HTTP APIs implemented on v11.2.5.
- Fix #1335 (comment)
- Add
ProblemOptions
withRetryAfter
as requested at: #1335 (comment). - Add
iris.JSON
alias forcontext#JSON
options type.
Example updated.
References:
Commit log: https://github.com/kataras/iris/compare/v11.2.6...v11.2.7
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
Commit log: https://github.com/kataras/iris/compare/v11.2.4...v11.2.5
- 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
- New Feature: Handle different parameter types in the same path
- New Feature: Content Negotiation
- Context.ReadYAML
- Fixes kataras/neffos#1 (comment)
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.
Read about the new release at: https://www.facebook.com/iris.framework/posts/3276606095684693