mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 10:41:03 +01:00
resolve conflicts with current master v11.1.1
Former-commit-id: 659ff392e889f3a8552d7da3d44848f1a364f7b2
This commit is contained in:
commit
736709aa75
5
.github/FUNDING.yml
vendored
Normal file
5
.github/FUNDING.yml
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
# patreon: # Replace with a single Patreon username
|
||||
# open_collective: # Replace with a single Open Collective username
|
||||
# ko_fi: # Replace with a single Ko-fi username
|
||||
# tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
custom: https://iris-go.com/donate # Replace with a single custom sponsorship URL
|
Binary file not shown.
After Width: | Height: | Size: 74 KiB |
2
_examples/cache/simple/main.go
vendored
2
_examples/cache/simple/main.go
vendored
|
@ -61,7 +61,7 @@ func main() {
|
|||
app.Logger().SetLevel("debug")
|
||||
app.Get("/", cache.Handler(10*time.Second), writeMarkdown)
|
||||
// saves its content on the first request and serves it instead of re-calculating the content.
|
||||
// After 10 seconds it will be cleared and resetted.
|
||||
// After 10 seconds it will be cleared and reset.
|
||||
|
||||
app.Run(iris.Addr(":8080"))
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ func main() {
|
|||
ctx.Writef("Hello from %s", ctx.Path())
|
||||
})
|
||||
|
||||
// Any custom fields here. Handler and ErrorLog are setted to the server automatically
|
||||
// Any custom fields here. Handler and ErrorLog are set to the server automatically
|
||||
srv := &http.Server{Addr: ":8080"}
|
||||
|
||||
// http://localhost:8080/
|
||||
|
|
|
@ -22,10 +22,10 @@ func newApp() *iris.Application {
|
|||
// it tries to find the language by:
|
||||
// ctx.Values().GetString("language")
|
||||
// if that was empty then
|
||||
// it tries to find from the URLParameter setted on the configuration
|
||||
// it tries to find from the URLParameter set on the configuration
|
||||
// if not found then
|
||||
// it tries to find the language by the "language" cookie
|
||||
// if didn't found then it it set to the Default setted on the configuration
|
||||
// if didn't found then it it set to the Default set on the configuration
|
||||
|
||||
// hi is the key, 'iris' is the %s on the .ini file
|
||||
// the second parameter is optional
|
||||
|
|
|
@ -966,7 +966,7 @@ type Context interface {
|
|||
// ContentType sets the response writer's header key "Content-Type" to the 'cType'.
|
||||
ContentType(cType string)
|
||||
// GetContentType returns the response writer's header value of "Content-Type"
|
||||
// which may, setted before with the 'ContentType'.
|
||||
// which may, set before with the 'ContentType'.
|
||||
GetContentType() string
|
||||
// GetContentType returns the request's header value of "Content-Type".
|
||||
GetContentTypeRequested() string
|
||||
|
@ -1259,7 +1259,7 @@ type Context interface {
|
|||
//
|
||||
// This function may be used in the following cases:
|
||||
//
|
||||
// * if response body is too big (more than iris.LimitRequestBodySize(if setted)).
|
||||
// * if response body is too big (more than iris.LimitRequestBodySize(if set)).
|
||||
// * if response body is streamed from slow external sources.
|
||||
// * if response body must be streamed to the client in chunks.
|
||||
// (aka `http server push`).
|
||||
|
@ -1299,7 +1299,7 @@ type Context interface {
|
|||
// is being called afterwards, in the same request.
|
||||
// Useful when need to set or/and change a layout based on the previous handlers in the chain.
|
||||
//
|
||||
// Note that the 'layoutTmplFile' argument can be setted to iris.NoLayout || view.NoLayout
|
||||
// Note that the 'layoutTmplFile' argument can be set to iris.NoLayout || view.NoLayout
|
||||
// to disable the layout for a specific view render action,
|
||||
// it disables the engine's configuration's layout property.
|
||||
//
|
||||
|
|
|
@ -44,7 +44,7 @@ func main() {
|
|||
//set session values
|
||||
s.Set("name", "iris")
|
||||
|
||||
//test if setted here
|
||||
//test if set here
|
||||
ctx.Writef("All ok session value of the 'name' is: %s", s.GetString("name"))
|
||||
})
|
||||
|
||||
|
@ -54,7 +54,7 @@ func main() {
|
|||
// set session values
|
||||
s.Set(key, value)
|
||||
|
||||
// test if setted here
|
||||
// test if set here
|
||||
ctx.Writef("All ok session value of the '%s' is: %s", key, s.GetString(key))
|
||||
})
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ func main() {
|
|||
//set session values
|
||||
s.Set("name", "iris")
|
||||
|
||||
//test if setted here
|
||||
//test if set here
|
||||
ctx.Writef("All ok session value of the 'name' is: %s", s.GetString("name"))
|
||||
})
|
||||
|
||||
|
@ -55,7 +55,7 @@ func main() {
|
|||
// set session values
|
||||
s.Set(key, value)
|
||||
|
||||
// test if setted here
|
||||
// test if set here
|
||||
ctx.Writef("All ok session value of the '%s' is: %s", key, s.GetString(key))
|
||||
})
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ func main() {
|
|||
//set session values
|
||||
s.Set("name", "iris")
|
||||
|
||||
//test if setted here
|
||||
//test if set here
|
||||
ctx.Writef("All ok session value of the 'name' is: %s", s.GetString("name"))
|
||||
})
|
||||
|
||||
|
@ -63,7 +63,7 @@ func main() {
|
|||
// set session values
|
||||
s.Set(key, value)
|
||||
|
||||
// test if setted here
|
||||
// test if set here
|
||||
ctx.Writef("All ok session value of the '%s' is: %s", key, s.GetString(key))
|
||||
})
|
||||
|
||||
|
@ -74,7 +74,7 @@ func main() {
|
|||
// set session values
|
||||
s.Set(key, value)
|
||||
valueSet := s.Get(key)
|
||||
// test if setted here
|
||||
// test if set here
|
||||
ctx.Writef("All ok session value of the '%s' is: %v", key, valueSet)
|
||||
})
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ func main() {
|
|||
app.Get("/set", func(ctx iris.Context) {
|
||||
s := sess.Start(ctx)
|
||||
s.SetFlash("name", "iris")
|
||||
ctx.Writef("Message setted, is available for the next request")
|
||||
ctx.Writef("Message set, is available for the next request")
|
||||
})
|
||||
|
||||
app.Get("/get", func(ctx iris.Context) {
|
||||
|
|
|
@ -39,8 +39,8 @@ func newApp() *iris.Application {
|
|||
s := mySessions.Start(ctx)
|
||||
s.Set("name", "iris")
|
||||
|
||||
//test if setted here
|
||||
ctx.Writef("All ok session setted to: %s", s.GetString("name"))
|
||||
//test if set here
|
||||
ctx.Writef("All ok session set to: %s", s.GetString("name"))
|
||||
})
|
||||
|
||||
app.Get("/get", func(ctx iris.Context) {
|
||||
|
|
|
@ -14,14 +14,14 @@ func TestSessionsEncodeDecode(t *testing.T) {
|
|||
es := e.GET("/set").Expect()
|
||||
es.Status(iris.StatusOK)
|
||||
es.Cookies().NotEmpty()
|
||||
es.Body().Equal("All ok session setted to: iris")
|
||||
es.Body().Equal("All ok session set to: iris")
|
||||
|
||||
e.GET("/get").Expect().Status(iris.StatusOK).Body().Equal("The name on the /set was: iris")
|
||||
// delete and re-get
|
||||
e.GET("/delete").Expect().Status(iris.StatusOK)
|
||||
e.GET("/get").Expect().Status(iris.StatusOK).Body().Equal("The name on the /set was: ")
|
||||
// set, clear and re-get
|
||||
e.GET("/set").Expect().Body().Equal("All ok session setted to: iris")
|
||||
e.GET("/set").Expect().Body().Equal("All ok session set to: iris")
|
||||
e.GET("/clear").Expect().Status(iris.StatusOK)
|
||||
e.GET("/get").Expect().Status(iris.StatusOK).Body().Equal("The name on the /set was: ")
|
||||
}
|
||||
|
|
|
@ -44,8 +44,8 @@ func main() {
|
|||
s := sess.Start(ctx)
|
||||
s.Set("name", "iris")
|
||||
|
||||
//test if setted here.
|
||||
ctx.Writef("All ok session setted to: %s", s.GetString("name"))
|
||||
//test if set here.
|
||||
ctx.Writef("All ok session set to: %s", s.GetString("name"))
|
||||
|
||||
// Set will set the value as-it-is,
|
||||
// if it's a slice or map
|
||||
|
|
|
@ -29,7 +29,7 @@ func main() {
|
|||
})
|
||||
|
||||
app.Get("/", func(ctx iris.Context) {
|
||||
ctx.ViewData("BodyMessage", "a sample text here... setted by the route handler")
|
||||
ctx.ViewData("BodyMessage", "a sample text here... set by the route handler")
|
||||
if err := ctx.View("index.html"); err != nil {
|
||||
ctx.Application().Logger().Infof(err.Error())
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ func main() {
|
|||
|
||||
app.Get("/about", func(ctx iris.Context) {
|
||||
ctx.ViewData("Title", "My About Page")
|
||||
ctx.ViewData("BodyMessage", "about text here... setted by the route handler")
|
||||
ctx.ViewData("BodyMessage", "about text here... set by the route handler")
|
||||
|
||||
// same file, just to keep things simple.
|
||||
if err := ctx.View("index.html"); err != nil {
|
||||
|
|
4
cache/browser_test.go
vendored
4
cache/browser_test.go
vendored
|
@ -91,13 +91,13 @@ func TestETag(t *testing.T) {
|
|||
e := httptest.New(t, app)
|
||||
|
||||
r := e.GET("/").Expect().Status(httptest.StatusOK)
|
||||
r.Header("ETag").Equal("/") // test if header setted.
|
||||
r.Header("ETag").Equal("/") // test if header set.
|
||||
r.Body().Equal("_")
|
||||
|
||||
e.GET("/").WithHeader("ETag", "/").WithHeader("If-None-Match", "/").Expect().
|
||||
Status(httptest.StatusNotModified).Body().Equal("") // browser is responsible, no the test engine.
|
||||
|
||||
r = e.GET("/").Expect().Status(httptest.StatusOK)
|
||||
r.Header("ETag").Equal("/") // test if header setted.
|
||||
r.Header("ETag").Equal("/") // test if header set.
|
||||
r.Body().Equal("__")
|
||||
}
|
||||
|
|
2
cache/cfg/cfg.go
vendored
2
cache/cfg/cfg.go
vendored
|
@ -16,7 +16,7 @@ var (
|
|||
RequestCacheTimeout = 5 * time.Second
|
||||
)
|
||||
|
||||
// NoCacheHeader is the static header key which is setted to the response when NoCache is called,
|
||||
// NoCacheHeader is the static header key which is set to the response when NoCache is called,
|
||||
// used inside nethttp and fhttp Skippers.
|
||||
var NoCacheHeader = "X-No-Cache"
|
||||
|
||||
|
|
2
cache/entry/response.go
vendored
2
cache/entry/response.go
vendored
|
@ -3,7 +3,7 @@ package entry
|
|||
import "net/http"
|
||||
|
||||
// Response is the cached response will be send to the clients
|
||||
// its fields setted at runtime on each of the non-cached executions
|
||||
// its fields set at runtime on each of the non-cached executions
|
||||
// non-cached executions = first execution, and each time after
|
||||
// cache expiration datetime passed.
|
||||
type Response struct {
|
||||
|
|
2
cache/uri/uribuilder.go
vendored
2
cache/uri/uribuilder.go
vendored
|
@ -62,7 +62,7 @@ func (r *URIBuilder) ContentType(s string) *URIBuilder {
|
|||
}
|
||||
|
||||
// String returns the full url which should be passed to get a cache entry response back
|
||||
// (it could be setted by server too but we need some client-freedom on the requested key)
|
||||
// (it could be set by server too but we need some client-freedom on the requested key)
|
||||
// in order to be sure that the registered cache entries are unique among different clients with the same key
|
||||
// note1: we do it manually*,
|
||||
// note2: on fasthttp that is not required because the query args added as expected but we will use it there too to be align with net/http
|
||||
|
|
|
@ -588,7 +588,7 @@ func (tc TunnelingConfiguration) createTunnel(tunnelAPIRequest ngrokTunnel, publ
|
|||
// these can be passed via options also, look at the top of this file(configuration.go).
|
||||
// Configuration is a valid OptionSetter.
|
||||
type Configuration struct {
|
||||
// vhost is private and setted only with .Run method, it cannot be changed after the first set.
|
||||
// vhost is private and set only with .Run method, it cannot be changed after the first set.
|
||||
// It can be retrieved by the context if needed (i.e router for subdomains)
|
||||
vhost string
|
||||
|
||||
|
@ -609,11 +609,11 @@ type Configuration struct {
|
|||
// Defaults to an empty slice.
|
||||
IgnoreServerErrors []string `json:"ignoreServerErrors,omitempty" yaml:"IgnoreServerErrors" toml:"IgnoreServerErrors"`
|
||||
|
||||
// DisableStartupLog if setted to true then it turns off the write banner on server startup.
|
||||
// DisableStartupLog if set to true then it turns off the write banner on server startup.
|
||||
//
|
||||
// Defaults to false.
|
||||
DisableStartupLog bool `json:"disableStartupLog,omitempty" yaml:"DisableStartupLog" toml:"DisableStartupLog"`
|
||||
// DisableInterruptHandler if setted to true then it disables the automatic graceful server shutdown
|
||||
// DisableInterruptHandler if set to true then it disables the automatic graceful server shutdown
|
||||
// when control/cmd+C pressed.
|
||||
// Turn this to true if you're planning to handle this by your own via a custom host.Task.
|
||||
//
|
||||
|
@ -662,11 +662,11 @@ type Configuration struct {
|
|||
FireMethodNotAllowed bool `json:"fireMethodNotAllowed,omitempty" yaml:"FireMethodNotAllowed" toml:"FireMethodNotAllowed"`
|
||||
|
||||
// DisableBodyConsumptionOnUnmarshal manages the reading behavior of the context's body readers/binders.
|
||||
// If setted to true then it
|
||||
// If set to true then it
|
||||
// disables the body consumption by the `context.UnmarshalBody/ReadJSON/ReadXML`.
|
||||
//
|
||||
// By-default io.ReadAll` is used to read the body from the `context.Request.Body which is an `io.ReadCloser`,
|
||||
// if this field setted to true then a new buffer will be created to read from and the request body.
|
||||
// if this field set to true then a new buffer will be created to read from and the request body.
|
||||
// The body will not be changed and existing data before the
|
||||
// context.UnmarshalBody/ReadJSON/ReadXML will be not consumed.
|
||||
DisableBodyConsumptionOnUnmarshal bool `json:"disableBodyConsumptionOnUnmarshal,omitempty" yaml:"DisableBodyConsumptionOnUnmarshal" toml:"DisableBodyConsumptionOnUnmarshal"`
|
||||
|
@ -678,7 +678,7 @@ type Configuration struct {
|
|||
// By-default a custom http error handler will be fired when "context.StatusCode(code)" called,
|
||||
// code should be equal with the result of the the `context.StatusCodeNotSuccessful` in order to be received as an "http error handler".
|
||||
//
|
||||
// Developer may want this option to setted as true in order to manually call the
|
||||
// Developer may want this option to set as true in order to manually call the
|
||||
// error handlers when needed via "context#FireStatusCode(< 200 || >= 400)".
|
||||
// HTTP Custom error handlers are being registered via app.OnErrorCode(code, handler)".
|
||||
//
|
||||
|
@ -807,7 +807,7 @@ func (c Configuration) GetFireMethodNotAllowed() bool {
|
|||
// is disabled.
|
||||
//
|
||||
// By-default io.ReadAll` is used to read the body from the `context.Request.Body which is an `io.ReadCloser`,
|
||||
// if this field setted to true then a new buffer will be created to read from and the request body.
|
||||
// if this field set to true then a new buffer will be created to read from and the request body.
|
||||
// The body will not be changed and existing data before the
|
||||
// context.UnmarshalBody/ReadJSON/ReadXML will be not consumed.
|
||||
func (c Configuration) GetDisableBodyConsumptionOnUnmarshal() bool {
|
||||
|
|
|
@ -61,7 +61,7 @@ func TestConfigurationOptions(t *testing.T) {
|
|||
t.Fatalf("Expected configuration DisableStartupLog to be: %#v but got: %#v", disableBanner, got)
|
||||
}
|
||||
|
||||
// now check if other default values are setted (should be setted automatically)
|
||||
// now check if other default values are set (should be set automatically)
|
||||
|
||||
expected := DefaultConfiguration()
|
||||
expected.Charset = charset
|
||||
|
|
|
@ -41,7 +41,7 @@ type ConfigurationReadOnly interface {
|
|||
// is disabled.
|
||||
//
|
||||
// By-default io.ReadAll` is used to read the body from the `context.Request.Body which is an `io.ReadCloser`,
|
||||
// if this field setted to true then a new buffer will be created to read from and the request body.
|
||||
// if this field set to true then a new buffer will be created to read from and the request body.
|
||||
// The body will not be changed and existing data before the
|
||||
// context.UnmarshalBody/ReadJSON/ReadXML will be not consumed.
|
||||
GetDisableBodyConsumptionOnUnmarshal() bool
|
||||
|
|
|
@ -369,7 +369,7 @@ type Context interface {
|
|||
// ContentType sets the response writer's header key "Content-Type" to the 'cType'.
|
||||
ContentType(cType string)
|
||||
// GetContentType returns the response writer's header value of "Content-Type"
|
||||
// which may, setted before with the 'ContentType'.
|
||||
// which may, set before with the 'ContentType'.
|
||||
GetContentType() string
|
||||
// GetContentType returns the request's header value of "Content-Type".
|
||||
GetContentTypeRequested() string
|
||||
|
@ -669,7 +669,7 @@ type Context interface {
|
|||
//
|
||||
// This function may be used in the following cases:
|
||||
//
|
||||
// * if response body is too big (more than iris.LimitRequestBodySize(if setted)).
|
||||
// * if response body is too big (more than iris.LimitRequestBodySize(if set)).
|
||||
// * if response body is streamed from slow external sources.
|
||||
// * if response body must be streamed to the client in chunks.
|
||||
// (aka `http server push`).
|
||||
|
@ -709,7 +709,7 @@ type Context interface {
|
|||
// is being called afterwards, in the same request.
|
||||
// Useful when need to set or/and change a layout based on the previous handlers in the chain.
|
||||
//
|
||||
// Note that the 'layoutTmplFile' argument can be setted to iris.NoLayout || view.NoLayout
|
||||
// Note that the 'layoutTmplFile' argument can be set to iris.NoLayout || view.NoLayout
|
||||
// to disable the layout for a specific view render action,
|
||||
// it disables the engine's configuration's layout property.
|
||||
//
|
||||
|
@ -1762,7 +1762,7 @@ func (ctx *context) ContentType(cType string) {
|
|||
}
|
||||
|
||||
// GetContentType returns the response writer's header value of "Content-Type"
|
||||
// which may, setted before with the 'ContentType'.
|
||||
// which may, set before with the 'ContentType'.
|
||||
func (ctx *context) GetContentType() string {
|
||||
return ctx.writer.Header().Get(ContentTypeHeaderKey)
|
||||
}
|
||||
|
@ -2597,7 +2597,7 @@ func (ctx *context) WriteWithExpiration(body []byte, modtime time.Time) (int, er
|
|||
//
|
||||
// This function may be used in the following cases:
|
||||
//
|
||||
// * if response body is too big (more than iris.LimitRequestBodySize(if setted)).
|
||||
// * if response body is too big (more than iris.LimitRequestBodySize(if set)).
|
||||
// * if response body is streamed from slow external sources.
|
||||
// * if response body must be streamed to the client in chunks.
|
||||
// (aka `http server push`).
|
||||
|
@ -2714,7 +2714,7 @@ const (
|
|||
// is being called afterwards, in the same request.
|
||||
// Useful when need to set or/and change a layout based on the previous handlers in the chain.
|
||||
//
|
||||
// Note that the 'layoutTmplFile' argument can be setted to iris.NoLayout || view.NoLayout || context.NoLayout
|
||||
// Note that the 'layoutTmplFile' argument can be set to iris.NoLayout || view.NoLayout || context.NoLayout
|
||||
// to disable the layout for a specific view render action,
|
||||
// it disables the engine's configuration's layout property.
|
||||
//
|
||||
|
|
|
@ -18,7 +18,7 @@ type compressionPool struct {
|
|||
// |GZIP raw io.writer, our gzip response writer will use that. |
|
||||
// +------------------------------------------------------------+
|
||||
|
||||
// default writer pool with Compressor's level setted to -1
|
||||
// default writer pool with Compressor's level set to -1
|
||||
var gzipPool = &compressionPool{Level: -1}
|
||||
|
||||
// acquireGzipWriter prepares a gzip writer and returns it.
|
||||
|
|
|
@ -70,7 +70,7 @@ type ResponseWriter interface {
|
|||
|
||||
// SetBeforeFlush registers the unique callback which called exactly before the response is flushed to the client.
|
||||
SetBeforeFlush(cb func())
|
||||
// GetBeforeFlush returns (not execute) the before flush callback, or nil if not setted by SetBeforeFlush.
|
||||
// GetBeforeFlush returns (not execute) the before flush callback, or nil if not set by SetBeforeFlush.
|
||||
GetBeforeFlush() func()
|
||||
// FlushResponse should be called only once before EndResponse.
|
||||
// it tries to send the status code if not sent already
|
||||
|
|
|
@ -155,7 +155,7 @@ var RequestTransactionScope = TransactionScopeFunc(func(maybeErr TransactionErrR
|
|||
|
||||
// we need to register a beforeResponseFlush event here in order
|
||||
// to execute last the FireStatusCode
|
||||
// (which will reset the whole response's body, status code and headers setted from normal flow or other transactions too)
|
||||
// (which will reset the whole response's body, status code and headers set from normal flow or other transactions too)
|
||||
ctx.ResponseWriter().SetBeforeFlush(func() {
|
||||
// we need to re-take the context's response writer
|
||||
// because inside here the response writer is changed to the original's
|
||||
|
|
|
@ -582,7 +582,7 @@ func (e Entry) BoolDefault(def bool) (bool, error) {
|
|||
// respects the immutable.
|
||||
func (e Entry) Value() interface{} {
|
||||
if e.immutable {
|
||||
// take its value, no pointer even if setted with a reference.
|
||||
// take its value, no pointer even if set with a reference.
|
||||
vv := reflect.Indirect(reflect.ValueOf(e.ValueRaw))
|
||||
|
||||
// return copy of that slice
|
||||
|
|
|
@ -127,7 +127,7 @@ func ResolveAddr(addr string) string {
|
|||
if a[portIdx:] == ":https" {
|
||||
a = defaultServerHostname + ":443"
|
||||
} else {
|
||||
// if contains only :port ,then the : is the first letter, so we dont have setted a hostname, lets set it
|
||||
// if contains only :port ,then the : is the first letter, so we dont have set a hostname, lets set it
|
||||
a = defaultServerHostname + a
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ func (ch *ErrorCodeHandler) Fire(ctx context.Context) {
|
|||
// if we can reset the body
|
||||
if w, ok := ctx.IsRecording(); ok {
|
||||
if statusCodeSuccessful(w.StatusCode()) { // if not an error status code
|
||||
w.WriteHeader(ch.StatusCode) // then set it manually here, otherwise it should be setted via ctx.StatusCode(...)
|
||||
w.WriteHeader(ch.StatusCode) // then set it manually here, otherwise it should be set via ctx.StatusCode(...)
|
||||
}
|
||||
// reset if previous content and it's recorder, keep the status code.
|
||||
w.ClearHeaders()
|
||||
|
|
|
@ -48,7 +48,7 @@ func (c Configuration) Set(main *Configuration) {
|
|||
}
|
||||
|
||||
var (
|
||||
// URL if setted then it sets the httptest's BaseURL.
|
||||
// URL if set then it sets the httptest's BaseURL.
|
||||
// Defaults to empty string "".
|
||||
URL = func(schemeAndHost string) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
|
|
|
@ -78,7 +78,7 @@ func (p *ParamParser) appendErr(format string, a ...interface{}) {
|
|||
|
||||
const (
|
||||
// DefaultParamErrorCode is the default http error code, 404 not found,
|
||||
// per-parameter. An error code can be setted via
|
||||
// per-parameter. An error code can be set via
|
||||
// the "else" keyword inside a route's path.
|
||||
DefaultParamErrorCode = 404
|
||||
)
|
||||
|
|
|
@ -102,7 +102,7 @@ func New(c Config) context.Handler {
|
|||
}
|
||||
}
|
||||
}
|
||||
// if not default language setted then set to the first of the i.config.Languages
|
||||
// if not default language set then set to the first of the i.config.Languages
|
||||
if c.Default == "" {
|
||||
c.Default = firstlanguage
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ type Config struct {
|
|||
// the contents with `ctx.Values().Get(MessageContextKey)`
|
||||
// and if available then these contents will be
|
||||
// appended as part of the logs (with `%v`, in order to be able to set a struct too),
|
||||
// if Columns field was setted to true then
|
||||
// if Columns field was set to true then
|
||||
// a new column will be added named 'Message'.
|
||||
//
|
||||
// Defaults to empty.
|
||||
|
@ -59,7 +59,7 @@ type Config struct {
|
|||
// the contents with `ctx.Values().Get(MessageHeaderKey)`
|
||||
// and if available then these contents will be
|
||||
// appended as part of the logs (with `%v`, in order to be able to set a struct too),
|
||||
// if Columns field was setted to true then
|
||||
// if Columns field was set to true then
|
||||
// a new column will be added named 'HeaderMessage'.
|
||||
//
|
||||
// Defaults to empty.
|
||||
|
|
|
@ -19,7 +19,7 @@ type Encoding interface {
|
|||
// Encode the cookie value if not nil.
|
||||
// Should accept as first argument the cookie name (config.Name)
|
||||
// as second argument the server's generated session id.
|
||||
// Should return the new session id, if error the session id setted to empty which is invalid.
|
||||
// Should return the new session id, if error the session id set to empty which is invalid.
|
||||
//
|
||||
// Note: Errors are not printed, so you have to know what you're doing,
|
||||
// and remember: if you use AES it only supports key sizes of 16, 24 or 32 bytes.
|
||||
|
@ -49,10 +49,10 @@ type (
|
|||
Cookie string
|
||||
|
||||
// CookieSecureTLS set to true if server is running over TLS
|
||||
// and you need the session's cookie "Secure" field to be setted true.
|
||||
// and you need the session's cookie "Secure" field to be set true.
|
||||
//
|
||||
// Note: The user should fill the Decode configuration field in order for this to work.
|
||||
// Recommendation: You don't need this to be setted to true, just fill the Encode and Decode fields
|
||||
// Note: The user should fill the Decode configuation field in order for this to work.
|
||||
// Recommendation: You don't need this to be set to true, just fill the Encode and Decode fields
|
||||
// with a third-party library like secure cookie, example is provided at the _examples folder.
|
||||
//
|
||||
// Defaults to false.
|
||||
|
@ -69,7 +69,7 @@ type (
|
|||
// Encode the cookie value if not nil.
|
||||
// Should accept as first argument the cookie name (config.Cookie)
|
||||
// as second argument the server's generated session id.
|
||||
// Should return the new session id, if error the session id setted to empty which is invalid.
|
||||
// Should return the new session id, if error the session id set to empty which is invalid.
|
||||
//
|
||||
// Note: Errors are not printed, so you have to know what you're doing,
|
||||
// and remember: if you use AES it only supports key sizes of 16, 24 or 32 bytes.
|
||||
|
|
331
sessions/sessiondb/redis/service/service.go
Normal file
331
sessions/sessiondb/redis/service/service.go
Normal file
|
@ -0,0 +1,331 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/gomodule/redigo/redis"
|
||||
"github.com/kataras/iris/core/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrRedisClosed an error with message 'Redis is already closed'
|
||||
ErrRedisClosed = errors.New("Redis is already closed")
|
||||
// ErrKeyNotFound an error with message 'Key $thekey doesn't found'
|
||||
ErrKeyNotFound = errors.New("Key '%s' doesn't found")
|
||||
)
|
||||
|
||||
// Service the Redis service, contains the config and the redis pool
|
||||
type Service struct {
|
||||
// Connected is true when the Service has already connected
|
||||
Connected bool
|
||||
// Config the redis config for this redis
|
||||
Config *Config
|
||||
pool *redis.Pool
|
||||
}
|
||||
|
||||
// PingPong sends a ping and receives a pong, if no pong received then returns false and filled error
|
||||
func (r *Service) PingPong() (bool, error) {
|
||||
c := r.pool.Get()
|
||||
defer c.Close()
|
||||
msg, err := c.Do("PING")
|
||||
if err != nil || msg == nil {
|
||||
return false, err
|
||||
}
|
||||
return (msg == "PONG"), nil
|
||||
}
|
||||
|
||||
// CloseConnection closes the redis connection
|
||||
func (r *Service) CloseConnection() error {
|
||||
if r.pool != nil {
|
||||
return r.pool.Close()
|
||||
}
|
||||
return ErrRedisClosed
|
||||
}
|
||||
|
||||
// Set sets a key-value to the redis store.
|
||||
// The expiration is set by the MaxAgeSeconds.
|
||||
func (r *Service) Set(key string, value interface{}, secondsLifetime int64) (err error) {
|
||||
c := r.pool.Get()
|
||||
defer c.Close()
|
||||
if c.Err() != nil {
|
||||
return c.Err()
|
||||
}
|
||||
|
||||
// if has expiration, then use the "EX" to delete the key automatically.
|
||||
if secondsLifetime > 0 {
|
||||
_, err = c.Do("SETEX", r.Config.Prefix+key, secondsLifetime, value)
|
||||
} else {
|
||||
_, err = c.Do("SET", r.Config.Prefix+key, value)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Get returns value, err by its key
|
||||
//returns nil and a filled error if something bad happened.
|
||||
func (r *Service) Get(key string) (interface{}, error) {
|
||||
c := r.pool.Get()
|
||||
defer c.Close()
|
||||
if err := c.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
redisVal, err := c.Do("GET", r.Config.Prefix+key)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if redisVal == nil {
|
||||
return nil, ErrKeyNotFound.Format(key)
|
||||
}
|
||||
return redisVal, nil
|
||||
}
|
||||
|
||||
// TTL returns the seconds to expire, if the key has expiration and error if action failed.
|
||||
// Read more at: https://redis.io/commands/ttl
|
||||
func (r *Service) TTL(key string) (seconds int64, hasExpiration bool, found bool) {
|
||||
c := r.pool.Get()
|
||||
defer c.Close()
|
||||
redisVal, err := c.Do("TTL", r.Config.Prefix+key)
|
||||
if err != nil {
|
||||
return -2, false, false
|
||||
}
|
||||
seconds = redisVal.(int64)
|
||||
// if -1 means the key has unlimited life time.
|
||||
hasExpiration = seconds > -1
|
||||
// if -2 means key does not exist.
|
||||
found = !(c.Err() != nil || seconds == -2)
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Service) updateTTLConn(c redis.Conn, key string, newSecondsLifeTime int64) error {
|
||||
reply, err := c.Do("EXPIRE", r.Config.Prefix+key, newSecondsLifeTime)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// https://redis.io/commands/expire#return-value
|
||||
//
|
||||
// 1 if the timeout was set.
|
||||
// 0 if key does not exist.
|
||||
if hadTTLOrExists, ok := reply.(int); ok {
|
||||
if hadTTLOrExists == 1 {
|
||||
return nil
|
||||
} else if hadTTLOrExists == 0 {
|
||||
return fmt.Errorf("unable to update expiration, the key '%s' was stored without ttl", key)
|
||||
} // do not check for -1.
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateTTL will update the ttl of a key.
|
||||
// Using the "EXPIRE" command.
|
||||
// Read more at: https://redis.io/commands/expire#refreshing-expires
|
||||
func (r *Service) UpdateTTL(key string, newSecondsLifeTime int64) error {
|
||||
c := r.pool.Get()
|
||||
defer c.Close()
|
||||
err := c.Err()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return r.updateTTLConn(c, key, newSecondsLifeTime)
|
||||
}
|
||||
|
||||
// UpdateTTLMany like `UpdateTTL` but for all keys starting with that "prefix",
|
||||
// it is a bit faster operation if you need to update all sessions keys (although it can be even faster if we used hash but this will limit other features),
|
||||
// look the `sessions/Database#OnUpdateExpiration` for example.
|
||||
func (r *Service) UpdateTTLMany(prefix string, newSecondsLifeTime int64) error {
|
||||
c := r.pool.Get()
|
||||
defer c.Close()
|
||||
if err := c.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
keys, err := r.getKeysConn(c, prefix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, key := range keys {
|
||||
if err = r.updateTTLConn(c, key, newSecondsLifeTime); err != nil { // fail on first error.
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// GetAll returns all redis entries using the "SCAN" command (2.8+).
|
||||
func (r *Service) GetAll() (interface{}, error) {
|
||||
c := r.pool.Get()
|
||||
defer c.Close()
|
||||
if err := c.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
redisVal, err := c.Do("SCAN", 0) // 0 -> cursor
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if redisVal == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return redisVal, nil
|
||||
}
|
||||
|
||||
func (r *Service) getKeysConn(c redis.Conn, prefix string) ([]string, error) {
|
||||
if err := c.Send("SCAN", 0, "MATCH", r.Config.Prefix+prefix+"*", "COUNT", 9999999999); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := c.Flush(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reply, err := c.Receive()
|
||||
if err != nil || reply == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// it returns []interface, with two entries, the first one is "0" and the second one is a slice of the keys as []interface{uint8....}.
|
||||
|
||||
if keysInterface, ok := reply.([]interface{}); ok {
|
||||
if len(keysInterface) == 2 {
|
||||
// take the second, it must contain the slice of keys.
|
||||
if keysSliceAsBytes, ok := keysInterface[1].([]interface{}); ok {
|
||||
keys := make([]string, len(keysSliceAsBytes), len(keysSliceAsBytes))
|
||||
for i, k := range keysSliceAsBytes {
|
||||
keys[i] = fmt.Sprintf("%s", k)[len(r.Config.Prefix):]
|
||||
}
|
||||
|
||||
return keys, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// GetKeys returns all redis keys using the "SCAN" with MATCH command.
|
||||
// Read more at: https://redis.io/commands/scan#the-match-option.
|
||||
func (r *Service) GetKeys(prefix string) ([]string, error) {
|
||||
c := r.pool.Get()
|
||||
defer c.Close()
|
||||
if err := c.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return r.getKeysConn(c, prefix)
|
||||
}
|
||||
|
||||
// GetBytes returns value, err by its key
|
||||
// you can use utils.Deserialize((.GetBytes("yourkey"),&theobject{})
|
||||
//returns nil and a filled error if something wrong happens
|
||||
func (r *Service) GetBytes(key string) ([]byte, error) {
|
||||
c := r.pool.Get()
|
||||
defer c.Close()
|
||||
if err := c.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
redisVal, err := c.Do("GET", r.Config.Prefix+key)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if redisVal == nil {
|
||||
return nil, ErrKeyNotFound.Format(key)
|
||||
}
|
||||
|
||||
return redis.Bytes(redisVal, err)
|
||||
}
|
||||
|
||||
// Delete removes redis entry by specific key
|
||||
func (r *Service) Delete(key string) error {
|
||||
c := r.pool.Get()
|
||||
defer c.Close()
|
||||
|
||||
_, err := c.Do("DEL", r.Config.Prefix+key)
|
||||
return err
|
||||
}
|
||||
|
||||
func dial(network string, addr string, pass string) (redis.Conn, error) {
|
||||
if network == "" {
|
||||
network = DefaultRedisNetwork
|
||||
}
|
||||
if addr == "" {
|
||||
addr = DefaultRedisAddr
|
||||
}
|
||||
c, err := redis.Dial(network, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if pass != "" {
|
||||
if _, err = c.Do("AUTH", pass); err != nil {
|
||||
c.Close()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return c, err
|
||||
}
|
||||
|
||||
// Connect connects to the redis, called only once
|
||||
func (r *Service) Connect() {
|
||||
c := r.Config
|
||||
|
||||
if c.IdleTimeout <= 0 {
|
||||
c.IdleTimeout = DefaultRedisIdleTimeout
|
||||
}
|
||||
|
||||
if c.Network == "" {
|
||||
c.Network = DefaultRedisNetwork
|
||||
}
|
||||
|
||||
if c.Addr == "" {
|
||||
c.Addr = DefaultRedisAddr
|
||||
}
|
||||
|
||||
pool := &redis.Pool{IdleTimeout: c.IdleTimeout, MaxIdle: c.MaxIdle, MaxActive: c.MaxActive}
|
||||
pool.TestOnBorrow = func(c redis.Conn, t time.Time) error {
|
||||
_, err := c.Do("PING")
|
||||
return err
|
||||
}
|
||||
|
||||
if c.Database != "" {
|
||||
pool.Dial = func() (redis.Conn, error) {
|
||||
red, err := dial(c.Network, c.Addr, c.Password)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err = red.Do("SELECT", c.Database); err != nil {
|
||||
red.Close()
|
||||
return nil, err
|
||||
}
|
||||
return red, err
|
||||
}
|
||||
} else {
|
||||
pool.Dial = func() (redis.Conn, error) {
|
||||
return dial(c.Network, c.Addr, c.Password)
|
||||
}
|
||||
}
|
||||
r.Connected = true
|
||||
r.pool = pool
|
||||
}
|
||||
|
||||
// New returns a Redis service filled by the passed config
|
||||
// to connect call the .Connect().
|
||||
func New(cfg ...Config) *Service {
|
||||
c := DefaultConfig()
|
||||
if len(cfg) > 0 {
|
||||
c = cfg[0]
|
||||
}
|
||||
r := &Service{pool: &redis.Pool{}, Config: &c}
|
||||
return r
|
||||
}
|
|
@ -91,7 +91,7 @@ func testSessions(t *testing.T, sess *sessions.Sessions, app *iris.Application)
|
|||
d := e.GET("/destroy").Expect().Status(iris.StatusOK)
|
||||
d.JSON().Object().Empty()
|
||||
// This removed: d.Cookies().Empty(). Reason:
|
||||
// httpexpect counts the cookies setted or deleted at the response time, but cookie is not removed, to be really removed needs to SetExpire(now-1second) so,
|
||||
// httpexpect counts the cookies set or deleted at the response time, but cookie is not removed, to be really removed needs to SetExpire(now-1second) so,
|
||||
// test if the cookies removed on the next request, like the browser's behavior.
|
||||
e.GET("/after_destroy").Expect().Status(iris.StatusOK).Cookies().Empty()
|
||||
// set and clear again
|
||||
|
|
|
@ -78,7 +78,7 @@ type (
|
|||
// 2. Dir: string, Dir set the root, where to search for typescript files/project. Default "./"
|
||||
// 3. Ignore: string, comma separated ignore typescript files/project from these directories. Default "" (node_modules are always ignored)
|
||||
// 4. Tsconfig: &typescript.Tsconfig{}, here you can set all compilerOptions if no tsconfig.json exists inside the 'Dir'
|
||||
// 5. Editor: typescript.Editor("username","password"), if setted then alm-tools browser-based typescript IDE will be available. Defailt is nil
|
||||
// 5. Editor: typescript.Editor("username","password"), if set then alm-tools browser-based typescript IDE will be available. Defailt is nil
|
||||
Config struct {
|
||||
// Bin the path of the tsc binary file
|
||||
// if empty then the plugin tries to find it
|
||||
|
|
|
@ -128,7 +128,7 @@ func hi(ctx iris.Context) {
|
|||
|
||||
View engine supports bundled(https://github.com/shuLhan/go-bindata) template files too.
|
||||
`go-bindata` gives you two functions, `Assset` and `AssetNames`,
|
||||
these can be setted to each of the template engines using the `.Binary` function.
|
||||
these can be set to each of the template engines using the `.Binary` function.
|
||||
|
||||
Example code:
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ func (s *AmberEngine) Binary(assetFn func(name string) ([]byte, error), namesFn
|
|||
return s
|
||||
}
|
||||
|
||||
// Reload if setted to true the templates are reloading on each render,
|
||||
// Reload if set to true the templates are reloading on each render,
|
||||
// use it when you're in development and you're boring of restarting
|
||||
// the whole app when you edit a template file.
|
||||
//
|
||||
|
@ -91,7 +91,7 @@ func (s *AmberEngine) Load() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// change the directory field configuration, load happens after directory has been setted, so we will not have any problems here.
|
||||
// change the directory field configuration, load happens after directory has been set, so we will not have any problems here.
|
||||
s.directory = dir
|
||||
return s.loadDirectory()
|
||||
}
|
||||
|
|
|
@ -135,7 +135,7 @@ func (s *DjangoEngine) Binary(assetFn func(name string) ([]byte, error), namesFn
|
|||
return s
|
||||
}
|
||||
|
||||
// Reload if setted to true the templates are reloading on each render,
|
||||
// Reload if set to true the templates are reloading on each render,
|
||||
// use it when you're in development and you're boring of restarting
|
||||
// the whole app when you edit a template file.
|
||||
//
|
||||
|
@ -210,7 +210,7 @@ func (s *DjangoEngine) Load() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// change the directory field configuration, load happens after directory has been setted, so we will not have any problems here.
|
||||
// change the directory field configuration, load happens after directory has been set, so we will not have any problems here.
|
||||
s.directory = dir
|
||||
return s.loadDirectory()
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ func (s *HandlebarsEngine) Binary(assetFn func(name string) ([]byte, error), nam
|
|||
return s
|
||||
}
|
||||
|
||||
// Reload if setted to true the templates are reloading on each render,
|
||||
// Reload if set to true the templates are reloading on each render,
|
||||
// use it when you're in development and you're boring of restarting
|
||||
// the whole app when you edit a template file.
|
||||
//
|
||||
|
@ -111,7 +111,7 @@ func (s *HandlebarsEngine) Load() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// change the directory field configuration, load happens after directory has been setted, so we will not have any problems here.
|
||||
// change the directory field configuration, load happens after directory has been set, so we will not have any problems here.
|
||||
s.directory = dir
|
||||
return s.loadDirectory()
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ func (s *HTMLEngine) Binary(assetFn func(name string) ([]byte, error), namesFn f
|
|||
return s
|
||||
}
|
||||
|
||||
// Reload if setted to true the templates are reloading on each render,
|
||||
// Reload if set to true the templates are reloading on each render,
|
||||
// use it when you're in development and you're boring of restarting
|
||||
// the whole app when you edit a template file.
|
||||
//
|
||||
|
@ -226,7 +226,7 @@ func (s *HTMLEngine) Load() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// change the directory field configuration, load happens after directory has been setted, so we will not have any problems here.
|
||||
// change the directory field configuration, load happens after directory has been set, so we will not have any problems here.
|
||||
s.directory = dir
|
||||
return s.loadDirectory()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user