mirror of
https://github.com/kataras/iris.git
synced 2025-12-23 12:57:05 +00:00
Update to 4.2.0 - Configuration changes (big but old way still works, naming changes) & Implement https://github.com/kataras/iris/issues/409
This commit is contained in:
859
configuration.go
Normal file
859
configuration.go
Normal file
@@ -0,0 +1,859 @@
|
||||
package iris
|
||||
|
||||
import (
|
||||
"github.com/imdario/mergo"
|
||||
"github.com/kataras/go-options"
|
||||
"github.com/kataras/go-sessions"
|
||||
"github.com/valyala/fasthttp"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type (
|
||||
// OptionSetter sets a configuration field to the main configuration
|
||||
// used to help developers to write less and configure only what they really want and nothing else
|
||||
// example:
|
||||
// iris.New(iris.Configuration{Sessions:iris.SessionConfiguration{Cookie:"mysessionid"}, Websocket: iris.WebsocketConfiguration{Endpoint:"/my_endpoint"}})
|
||||
// now can be done also by using iris.Option$FIELD:
|
||||
// iris.New(irisOptionSessionsCookie("mycookieid"),iris.OptionWebsocketEndpoint("my_endpoint"))
|
||||
// benefits:
|
||||
// 1. user/dev have no worries what option to pass, he/she can just press iris.Option and all options should be shown to her/his editor's autocomplete-popup window
|
||||
// 2. can be passed with any order
|
||||
// 3. Can override previous configuration
|
||||
OptionSetter interface {
|
||||
// Set receives a pointer to the global Configuration type and does the job of filling it
|
||||
Set(c *Configuration)
|
||||
}
|
||||
// OptionSet implements the OptionSetter
|
||||
OptionSet func(c *Configuration)
|
||||
)
|
||||
|
||||
// Set is the func which makes the OptionSet an OptionSetter, this is used mostly
|
||||
func (o OptionSet) Set(c *Configuration) {
|
||||
o(c)
|
||||
}
|
||||
|
||||
// Configuration the whole configuration for an iris instance ($instance.Config) or global iris instance (iris.Config)
|
||||
// these can be passed via options also, look at the top of this file(configuration.go)
|
||||
//
|
||||
// Configuration is also implements the OptionSet so it's a valid option itself, this is briliant enough
|
||||
type Configuration struct {
|
||||
// DisablePathCorrection corrects and redirects the requested path to the registed path
|
||||
// for example, if /home/ path is requested but no handler for this Route found,
|
||||
// then the Router checks if /home handler exists, if yes,
|
||||
// (permant)redirects the client to the correct path /home
|
||||
//
|
||||
// Default is false
|
||||
DisablePathCorrection bool
|
||||
|
||||
// DisablePathEscape when is false then its escapes the path, the named parameters (if any).
|
||||
// Change to true it if you want something like this https://github.com/kataras/iris/issues/135 to work
|
||||
//
|
||||
// When do you need to Disable(true) it:
|
||||
// accepts parameters with slash '/'
|
||||
// Request: http://localhost:8080/details/Project%2FDelta
|
||||
// ctx.Param("project") returns the raw named parameter: Project%2FDelta
|
||||
// which you can escape it manually with net/url:
|
||||
// projectName, _ := url.QueryUnescape(c.Param("project").
|
||||
// Look here: https://github.com/kataras/iris/issues/135 for more
|
||||
//
|
||||
// Default is false
|
||||
DisablePathEscape bool
|
||||
|
||||
// DisableBanner outputs the iris banner at startup
|
||||
//
|
||||
// Default is false
|
||||
DisableBanner bool
|
||||
|
||||
// LoggerOut is the destination for output
|
||||
//
|
||||
// Default is os.Stdout
|
||||
LoggerOut io.Writer
|
||||
// LoggerPreffix is the logger's prefix to write at beginning of each line
|
||||
//
|
||||
// Default is [IRIS]
|
||||
LoggerPreffix string
|
||||
|
||||
// ProfilePath a the route path, set it to enable http pprof tool
|
||||
// Default is empty, if you set it to a $path, these routes will handled:
|
||||
// $path/cmdline
|
||||
// $path/profile
|
||||
// $path/symbol
|
||||
// $path/goroutine
|
||||
// $path/heap
|
||||
// $path/threadcreate
|
||||
// $path/pprof/block
|
||||
// for example if '/debug/pprof'
|
||||
// http://yourdomain:PORT/debug/pprof/
|
||||
// http://yourdomain:PORT/debug/pprof/cmdline
|
||||
// http://yourdomain:PORT/debug/pprof/profile
|
||||
// http://yourdomain:PORT/debug/pprof/symbol
|
||||
// http://yourdomain:PORT/debug/pprof/goroutine
|
||||
// http://yourdomain:PORT/debug/pprof/heap
|
||||
// http://yourdomain:PORT/debug/pprof/threadcreate
|
||||
// http://yourdomain:PORT/debug/pprof/pprof/block
|
||||
// it can be a subdomain also, for example, if 'debug.'
|
||||
// http://debug.yourdomain:PORT/
|
||||
// http://debug.yourdomain:PORT/cmdline
|
||||
// http://debug.yourdomain:PORT/profile
|
||||
// http://debug.yourdomain:PORT/symbol
|
||||
// http://debug.yourdomain:PORT/goroutine
|
||||
// http://debug.yourdomain:PORT/heap
|
||||
// http://debug.yourdomain:PORT/threadcreate
|
||||
// http://debug.yourdomain:PORT/pprof/block
|
||||
ProfilePath string
|
||||
|
||||
// DisableTemplateEngines set to true to disable loading the default template engine (html/template) and disallow the use of iris.UseEngine
|
||||
// default is false
|
||||
DisableTemplateEngines bool
|
||||
|
||||
// IsDevelopment iris will act like a developer, for example
|
||||
// If true then re-builds the templates on each request
|
||||
// default is false
|
||||
IsDevelopment bool
|
||||
|
||||
// TimeFormat time format for any kind of datetime parsing
|
||||
TimeFormat string
|
||||
|
||||
// Charset character encoding for various rendering
|
||||
// used for templates and the rest of the responses
|
||||
// defaults to "UTF-8"
|
||||
Charset string
|
||||
|
||||
// Gzip enables gzip compression on your Render actions, this includes any type of render, templates and pure/raw content
|
||||
// If you don't want to enable it globaly, you could just use the third parameter on context.Render("myfileOrResponse", structBinding{}, iris.RenderOptions{"gzip": true})
|
||||
// defaults to false
|
||||
Gzip bool
|
||||
|
||||
// Sessions contains the configs for sessions
|
||||
Sessions SessionsConfiguration
|
||||
|
||||
// Websocket contains the configs for Websocket's server integration
|
||||
Websocket WebsocketConfiguration
|
||||
|
||||
// Tester contains the configs for the test framework, so far we have only one because all test framework's configs are setted by the iris itself
|
||||
// You can find example on the https://github.com/kataras/iris/glob/master/context_test.go
|
||||
Tester TesterConfiguration
|
||||
|
||||
// Other are the custom, dynamic options, can be empty
|
||||
// this fill used only by you to set any app's options you want
|
||||
// for each of an Iris instance
|
||||
Other options.Options
|
||||
}
|
||||
|
||||
// Set implements the OptionSetter
|
||||
func (c Configuration) Set(main *Configuration) {
|
||||
mergo.MergeWithOverwrite(main, c)
|
||||
}
|
||||
|
||||
// All options starts with "Option" preffix in order to be easier to find what dev searching for
|
||||
var (
|
||||
// OptionDisablePathCorrection corrects and redirects the requested path to the registed path
|
||||
// for example, if /home/ path is requested but no handler for this Route found,
|
||||
// then the Router checks if /home handler exists, if yes,
|
||||
// (permant)redirects the client to the correct path /home
|
||||
//
|
||||
// Default is false
|
||||
OptionDisablePathCorrection = func(val bool) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.DisablePathCorrection = val
|
||||
}
|
||||
|
||||
}
|
||||
// OptionDisablePathEscape when is false then its escapes the path, the named parameters (if any).
|
||||
OptionDisablePathEscape = func(val bool) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.DisablePathEscape = val
|
||||
}
|
||||
}
|
||||
// OptionDisableBanner outputs the iris banner at startup
|
||||
//
|
||||
// Default is false
|
||||
OptionDisableBanner = func(val bool) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.DisableBanner = val
|
||||
}
|
||||
}
|
||||
// OptionLoggerOut is the destination for output
|
||||
//
|
||||
// Default is os.Stdout
|
||||
OptionLoggerOut = func(val io.Writer) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.LoggerOut = val
|
||||
}
|
||||
}
|
||||
// OptionLoggerPreffix is the logger's prefix to write at beginning of each line
|
||||
//
|
||||
// Default is [IRIS]
|
||||
OptionLoggerPreffix = func(val string) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.LoggerPreffix = val
|
||||
}
|
||||
}
|
||||
// OptionProfilePath a the route path, set it to enable http pprof tool
|
||||
// Default is empty, if you set it to a $path, these routes will handled:
|
||||
OptionProfilePath = func(val string) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.ProfilePath = val
|
||||
}
|
||||
}
|
||||
// OptionDisableTemplateEngines set to true to disable loading the default template engine (html/template) and disallow the use of iris.UseEngine
|
||||
// Default is false
|
||||
OptionDisableTemplateEngines = func(val bool) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.DisableTemplateEngines = val
|
||||
}
|
||||
}
|
||||
// OptionIsDevelopment iris will act like a developer, for example
|
||||
// If true then re-builds the templates on each request
|
||||
// Default is false
|
||||
OptionIsDevelopment = func(val bool) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.IsDevelopment = val
|
||||
}
|
||||
}
|
||||
// OptionTimeFormat time format for any kind of datetime parsing
|
||||
OptionTimeFormat = func(val string) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.TimeFormat = val
|
||||
}
|
||||
}
|
||||
// OptionCharset character encoding for various rendering
|
||||
// used for templates and the rest of the responses
|
||||
// Default is "UTF-8"
|
||||
OptionCharset = func(val string) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.Charset = val
|
||||
}
|
||||
}
|
||||
// OptionGzip enables gzip compression on your Render actions, this includes any type of render, templates and pure/raw content
|
||||
// If you don't want to enable it globaly, you could just use the third parameter on context.Render("myfileOrResponse", structBinding{}, iris.RenderOptions{"gzip": true})
|
||||
// Default is false
|
||||
OptionGzip = func(val bool) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.Gzip = val
|
||||
}
|
||||
}
|
||||
|
||||
// OptionOther are the custom, dynamic options, can be empty
|
||||
// this fill used only by you to set any app's options you want
|
||||
// for each of an Iris instance
|
||||
OptionOther = func(val ...options.Options) OptionSet {
|
||||
opts := options.Options{}
|
||||
for _, opt := range val {
|
||||
for k, v := range opt {
|
||||
opts[k] = v
|
||||
}
|
||||
}
|
||||
return func(c *Configuration) {
|
||||
c.Other = opts
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultTimeFormat default time format for any kind of datetime parsing
|
||||
DefaultTimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT"
|
||||
// StaticCacheDuration expiration duration for INACTIVE file handlers, it's a global configuration field to all iris instances
|
||||
StaticCacheDuration = 20 * time.Second
|
||||
// CompressedFileSuffix is the suffix to add to the name of
|
||||
// cached compressed file when using the .StaticFS function.
|
||||
//
|
||||
// Defaults to iris-fasthttp.gz
|
||||
CompressedFileSuffix = "iris-fasthttp.gz"
|
||||
)
|
||||
|
||||
// Default values for base Iris conf
|
||||
const (
|
||||
DefaultDisablePathCorrection = false
|
||||
DefaultDisablePathEscape = false
|
||||
DefaultCharset = "UTF-8"
|
||||
DefaultLoggerPreffix = "[IRIS] "
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultLoggerOut is the default logger's output
|
||||
DefaultLoggerOut = os.Stdout
|
||||
)
|
||||
|
||||
// DefaultConfiguration returns the default configuration for an Iris station, fills the main Configuration
|
||||
func DefaultConfiguration() Configuration {
|
||||
return Configuration{
|
||||
DisablePathCorrection: DefaultDisablePathCorrection,
|
||||
DisablePathEscape: DefaultDisablePathEscape,
|
||||
DisableBanner: false,
|
||||
LoggerOut: DefaultLoggerOut,
|
||||
LoggerPreffix: DefaultLoggerPreffix,
|
||||
DisableTemplateEngines: false,
|
||||
IsDevelopment: false,
|
||||
TimeFormat: DefaultTimeFormat,
|
||||
Charset: DefaultCharset,
|
||||
Gzip: false,
|
||||
ProfilePath: "",
|
||||
Sessions: DefaultSessionsConfiguration(),
|
||||
Websocket: DefaultWebsocketConfiguration(),
|
||||
Tester: DefaultTesterConfiguration(),
|
||||
Other: options.Options{},
|
||||
}
|
||||
}
|
||||
|
||||
// SessionsConfiguration the configuration for sessions
|
||||
// has 6 fields
|
||||
// first is the cookieName, the session's name (string) ["mysessionsecretcookieid"]
|
||||
// second enable if you want to decode the cookie's key also
|
||||
// third is the time which the client's cookie expires
|
||||
// forth is the cookie length (sessionid) int, defaults to 32, do not change if you don't have any reason to do
|
||||
// fifth is the gcDuration (time.Duration) when this time passes it removes the unused sessions from the memory until the user come back
|
||||
// sixth is the DisableSubdomainPersistence which you can set it to true in order dissallow your q subdomains to have access to the session cook
|
||||
type SessionsConfiguration sessions.Config
|
||||
|
||||
var (
|
||||
// OptionSessionsCookie string, the session's client cookie name, for example: "qsessionid"
|
||||
OptionSessionsCookie = func(val string) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.Sessions.Cookie = val
|
||||
}
|
||||
}
|
||||
|
||||
// OptionSessionsDecodeCookie set it to true to decode the cookie key with base64 URLEncoding
|
||||
// Defaults to false
|
||||
OptionSessionsDecodeCookie = func(val bool) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.Sessions.DecodeCookie = val
|
||||
}
|
||||
}
|
||||
|
||||
// OptionSessionsExpires the duration of which the cookie must expires (created_time.Add(Expires)).
|
||||
// If you want to delete the cookie when the browser closes, set it to -1 but in this case, the server side's session duration is up to GcDuration
|
||||
//
|
||||
// Default infinitive/unlimited life duration(0)
|
||||
OptionSessionsExpires = func(val time.Duration) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.Sessions.Expires = val
|
||||
}
|
||||
}
|
||||
|
||||
// OptionSessionsCookieLength the length of the sessionid's cookie's value, let it to 0 if you don't want to change it
|
||||
// Defaults to 32
|
||||
OptionSessionsCookieLength = func(val int) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.Sessions.CookieLength = val
|
||||
}
|
||||
}
|
||||
|
||||
// OptionSessionsGcDuration every how much duration(GcDuration) the memory should be clear for unused cookies (GcDuration)
|
||||
// for example: time.Duration(2)*time.Hour. it will check every 2 hours if cookie hasn't be used for 2 hours,
|
||||
// deletes it from backend memory until the user comes back, then the session continue to work as it was
|
||||
//
|
||||
// Default 2 hours
|
||||
OptionSessionsGcDuration = func(val time.Duration) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.Sessions.GcDuration = val
|
||||
}
|
||||
}
|
||||
|
||||
// OptionSessionsDisableSubdomainPersistence set it to true in order dissallow your q subdomains to have access to the session cookie
|
||||
// defaults to false
|
||||
OptionSessionsDisableSubdomainPersistence = func(val bool) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.Sessions.DisableSubdomainPersistence = val
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
universe time.Time // 0001-01-01 00:00:00 +0000 UTC
|
||||
// CookieExpireNever the default cookie's life for sessions, unlimited (23 years)
|
||||
CookieExpireNever = time.Now().AddDate(23, 0, 0)
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultCookieName the secret cookie's name for sessions
|
||||
DefaultCookieName = "irissessionid"
|
||||
// DefaultSessionGcDuration is the default Session Manager's GCDuration , which is 2 hours
|
||||
DefaultSessionGcDuration = time.Duration(2) * time.Hour
|
||||
// DefaultCookieLength is the default Session Manager's CookieLength, which is 32
|
||||
DefaultCookieLength = 32
|
||||
)
|
||||
|
||||
// DefaultSessionsConfiguration the default configs for Sessions
|
||||
func DefaultSessionsConfiguration() SessionsConfiguration {
|
||||
return SessionsConfiguration{
|
||||
Cookie: DefaultCookieName,
|
||||
CookieLength: DefaultCookieLength,
|
||||
DecodeCookie: false,
|
||||
Expires: 0,
|
||||
GcDuration: DefaultSessionGcDuration,
|
||||
DisableSubdomainPersistence: false,
|
||||
}
|
||||
}
|
||||
|
||||
// WebsocketConfiguration the config contains options for the Websocket main config field
|
||||
type WebsocketConfiguration struct {
|
||||
// WriteTimeout time allowed to write a message to the connection.
|
||||
// Default value is 15 * time.Second
|
||||
WriteTimeout time.Duration
|
||||
// PongTimeout allowed to read the next pong message from the connection
|
||||
// Default value is 60 * time.Second
|
||||
PongTimeout time.Duration
|
||||
// PingPeriod send ping messages to the connection with this period. Must be less than PongTimeout
|
||||
// Default value is (PongTimeout * 9) / 10
|
||||
PingPeriod time.Duration
|
||||
// MaxMessageSize max message size allowed from connection
|
||||
// Default value is 1024
|
||||
MaxMessageSize int64
|
||||
// BinaryMessages set it to true in order to denotes binary data messages instead of utf-8 text
|
||||
// see https://github.com/kataras/iris/issues/387#issuecomment-243006022 for more
|
||||
// defaults to false
|
||||
BinaryMessages bool
|
||||
// Endpoint is the path which the websocket server will listen for clients/connections
|
||||
// Default value is empty string, if you don't set it the Websocket server is disabled.
|
||||
Endpoint string
|
||||
// ReadBufferSize is the buffer size for the underline reader
|
||||
ReadBufferSize int
|
||||
// WriteBufferSize is the buffer size for the underline writer
|
||||
WriteBufferSize int
|
||||
}
|
||||
|
||||
var (
|
||||
// OptionWebsocketWriteTimeout time allowed to write a message to the connection.
|
||||
// Default value is 15 * time.Second
|
||||
OptionWebsocketWriteTimeout = func(val time.Duration) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.Websocket.WriteTimeout = val
|
||||
}
|
||||
}
|
||||
// OptionWebsocketPongTimeout allowed to read the next pong message from the connection
|
||||
// Default value is 60 * time.Second
|
||||
OptionWebsocketPongTimeout = func(val time.Duration) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.Websocket.PongTimeout = val
|
||||
}
|
||||
}
|
||||
// OptionWebsocketPingPeriod send ping messages to the connection with this period. Must be less than PongTimeout
|
||||
// Default value is (PongTimeout * 9) / 10
|
||||
OptionWebsocketPingPeriod = func(val time.Duration) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.Websocket.PingPeriod = val
|
||||
}
|
||||
}
|
||||
// OptionWebsocketMaxMessageSize max message size allowed from connection
|
||||
// Default value is 1024
|
||||
OptionWebsocketMaxMessageSize = func(val int64) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.Websocket.MaxMessageSize = val
|
||||
}
|
||||
}
|
||||
// OptionWebsocketBinaryMessages set it to true in order to denotes binary data messages instead of utf-8 text
|
||||
// see https://github.com/kataras/iris/issues/387#issuecomment-243006022 for more
|
||||
// defaults to false
|
||||
OptionWebsocketBinaryMessages = func(val bool) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.Websocket.BinaryMessages = val
|
||||
}
|
||||
}
|
||||
// OptionWebsocketEndpoint is the path which the websocket server will listen for clients/connections
|
||||
// Default value is empty string, if you don't set it the Websocket server is disabled.
|
||||
OptionWebsocketEndpoint = func(val string) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.Websocket.Endpoint = val
|
||||
}
|
||||
}
|
||||
// OptionWebsocketReadBufferSize is the buffer size for the underline reader
|
||||
OptionWebsocketReadBufferSize = func(val int) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.Websocket.ReadBufferSize = val
|
||||
}
|
||||
}
|
||||
// OptionWebsocketWriteBufferSize is the buffer size for the underline writer
|
||||
OptionWebsocketWriteBufferSize = func(val int) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.Websocket.WriteBufferSize = val
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultWriteTimeout 15 * time.Second
|
||||
DefaultWriteTimeout = 15 * time.Second
|
||||
// DefaultPongTimeout 60 * time.Second
|
||||
DefaultPongTimeout = 60 * time.Second
|
||||
// DefaultPingPeriod (DefaultPongTimeout * 9) / 10
|
||||
DefaultPingPeriod = (DefaultPongTimeout * 9) / 10
|
||||
// DefaultMaxMessageSize 1024
|
||||
DefaultMaxMessageSize = 1024
|
||||
)
|
||||
|
||||
// DefaultWebsocketConfiguration returns the default config for iris-ws websocket package
|
||||
func DefaultWebsocketConfiguration() WebsocketConfiguration {
|
||||
return WebsocketConfiguration{
|
||||
WriteTimeout: DefaultWriteTimeout,
|
||||
PongTimeout: DefaultPongTimeout,
|
||||
PingPeriod: DefaultPingPeriod,
|
||||
MaxMessageSize: DefaultMaxMessageSize,
|
||||
BinaryMessages: false,
|
||||
ReadBufferSize: 4096,
|
||||
WriteBufferSize: 4096,
|
||||
Endpoint: "",
|
||||
}
|
||||
}
|
||||
|
||||
// TesterConfiguration configuration used inside main config field 'Tester'
|
||||
type TesterConfiguration struct {
|
||||
// ListeningAddr is the virtual server's listening addr (host)
|
||||
// Default is "iris-go.com:1993"
|
||||
ListeningAddr string
|
||||
// ExplicitURL If true then the url (should) be prepended manually, useful when want to test subdomains
|
||||
// Default is false
|
||||
ExplicitURL bool
|
||||
// Debug if true then debug messages from the httpexpect will be shown when a test runs
|
||||
// Default is false
|
||||
Debug bool
|
||||
}
|
||||
|
||||
var (
|
||||
// OptionTesterListeningAddr is the virtual server's listening addr (host)
|
||||
// Default is "iris-go.com:1993"
|
||||
OptionTesterListeningAddr = func(val string) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.Tester.ListeningAddr = val
|
||||
}
|
||||
}
|
||||
// OptionTesterExplicitURL If true then the url (should) be prepended manually, useful when want to test subdomains
|
||||
// Default is false
|
||||
OptionTesterExplicitURL = func(val bool) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.Tester.ExplicitURL = val
|
||||
}
|
||||
}
|
||||
// OptionTesterDebug if true then debug messages from the httpexpect will be shown when a test runs
|
||||
// Default is false
|
||||
OptionTesterDebug = func(val bool) OptionSet {
|
||||
return func(c *Configuration) {
|
||||
c.Tester.Debug = val
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// DefaultTesterConfiguration returns the default configuration for a tester
|
||||
// the ListeningAddr is used as virtual only when no running server is founded
|
||||
func DefaultTesterConfiguration() TesterConfiguration {
|
||||
return TesterConfiguration{ListeningAddr: "iris-go.com:1993", ExplicitURL: false, Debug: false}
|
||||
}
|
||||
|
||||
// ServerConfiguration is the configuration which is used inside iris' server(s) for listening to
|
||||
type ServerConfiguration struct {
|
||||
// ListenningAddr the addr that server listens to
|
||||
ListeningAddr string
|
||||
CertFile string
|
||||
KeyFile string
|
||||
// AutoTLS enable to get certifications from the Letsencrypt
|
||||
// when this configuration field is true, the CertFile & KeyFile are empty, no need to provide a key.
|
||||
//
|
||||
// example: https://github.com/iris-contrib/examples/blob/master/letsencyrpt/main.go
|
||||
AutoTLS bool
|
||||
// Mode this is for unix only
|
||||
Mode os.FileMode
|
||||
// MaxRequestBodySize Maximum request body size.
|
||||
//
|
||||
// The server rejects requests with bodies exceeding this limit.
|
||||
//
|
||||
// By default request body size is 8MB.
|
||||
MaxRequestBodySize int
|
||||
|
||||
// Per-connection buffer size for requests' reading.
|
||||
// This also limits the maximum header size.
|
||||
//
|
||||
// Increase this buffer if your clients send multi-KB RequestURIs
|
||||
// and/or multi-KB headers (for example, BIG cookies).
|
||||
//
|
||||
// Default buffer size is used if not set.
|
||||
ReadBufferSize int
|
||||
|
||||
// Per-connection buffer size for responses' writing.
|
||||
//
|
||||
// Default buffer size is used if not set.
|
||||
WriteBufferSize int
|
||||
|
||||
// Maximum duration for reading the full request (including body).
|
||||
//
|
||||
// This also limits the maximum duration for idle keep-alive
|
||||
// connections.
|
||||
//
|
||||
// By default request read timeout is unlimited.
|
||||
ReadTimeout time.Duration
|
||||
|
||||
// Maximum duration for writing the full response (including body).
|
||||
//
|
||||
// By default response write timeout is unlimited.
|
||||
WriteTimeout time.Duration
|
||||
|
||||
// RedirectTo, defaults to empty, set it in order to override the station's handler and redirect all requests to this address which is of form(HOST:PORT or :PORT)
|
||||
//
|
||||
// NOTE: the http status is 'StatusMovedPermanently', means one-time-redirect(the browser remembers the new addr and goes to the new address without need to request something from this server
|
||||
// which means that if you want to change this address you have to clear your browser's cache in order this to be able to change to the new addr.
|
||||
//
|
||||
// example: https://github.com/iris-contrib/examples/tree/master/multiserver_listening2
|
||||
RedirectTo string
|
||||
// Virtual If this server is not really listens to a real host, it mostly used in order to achieve testing without system modifications
|
||||
Virtual bool
|
||||
// VListeningAddr, can be used for both virtual = true or false,
|
||||
// if it's setted to not empty, then the server's Host() will return this addr instead of the ListeningAddr.
|
||||
// server's Host() is used inside global template helper funcs
|
||||
// set it when you are sure you know what it does.
|
||||
//
|
||||
// Default is empty ""
|
||||
VListeningAddr string
|
||||
// VScheme if setted to not empty value then all template's helper funcs prepends that as the url scheme instead of the real scheme
|
||||
// server's .Scheme returns VScheme if not empty && differs from real scheme
|
||||
//
|
||||
// Default is empty ""
|
||||
VScheme string
|
||||
// Name the server's name, defaults to "iris".
|
||||
// You're free to change it, but I will trust you to don't, this is the only setting whose somebody, like me, can see if iris web framework is used
|
||||
Name string
|
||||
}
|
||||
|
||||
// note: ServerConfiguration is the only one config which has its own option setter because
|
||||
// it's independent from a specific iris instance:
|
||||
// same server can run on multi iris instance
|
||||
// one iris instance/station can have and listening to more than one server.
|
||||
|
||||
// OptionServerSettter server configuration option setter
|
||||
type OptionServerSettter interface {
|
||||
Set(c *ServerConfiguration)
|
||||
}
|
||||
|
||||
// OptionServerSet is the func which implements the OptionServerSettter, this is used widely
|
||||
type OptionServerSet func(c *ServerConfiguration)
|
||||
|
||||
// Set is the func which makes OptionServerSet implements the OptionServerSettter
|
||||
func (o OptionServerSet) Set(c *ServerConfiguration) {
|
||||
o(c)
|
||||
}
|
||||
|
||||
// Set implements the OptionServerSettter to the ServerConfiguration
|
||||
func (c ServerConfiguration) Set(main *ServerConfiguration) {
|
||||
mergo.MergeWithOverwrite(main, c)
|
||||
}
|
||||
|
||||
// Options for ServerConfiguration
|
||||
var (
|
||||
OptionServerListeningAddr = func(val string) OptionServerSet {
|
||||
return func(c *ServerConfiguration) {
|
||||
c.ListeningAddr = val
|
||||
}
|
||||
}
|
||||
|
||||
OptionServerCertFile = func(val string) OptionServerSet {
|
||||
return func(c *ServerConfiguration) {
|
||||
c.CertFile = val
|
||||
}
|
||||
}
|
||||
|
||||
OptionServerKeyFile = func(val string) OptionServerSet {
|
||||
return func(c *ServerConfiguration) {
|
||||
c.KeyFile = val
|
||||
}
|
||||
}
|
||||
|
||||
// AutoTLS enable to get certifications from the Letsencrypt
|
||||
// when this configuration field is true, the CertFile & KeyFile are empty, no need to provide a key.
|
||||
//
|
||||
// example: https://github.com/iris-contrib/examples/blob/master/letsencyrpt/main.go
|
||||
OptionServerAutoTLS = func(val bool) OptionServerSet {
|
||||
return func(c *ServerConfiguration) {
|
||||
c.AutoTLS = val
|
||||
}
|
||||
}
|
||||
|
||||
// Mode this is for unix only
|
||||
OptionServerMode = func(val os.FileMode) OptionServerSet {
|
||||
return func(c *ServerConfiguration) {
|
||||
c.Mode = val
|
||||
}
|
||||
}
|
||||
|
||||
// OptionServerMaxRequestBodySize Maximum request body size.
|
||||
//
|
||||
// The server rejects requests with bodies exceeding this limit.
|
||||
//
|
||||
// By default request body size is 8MB.
|
||||
OptionServerMaxRequestBodySize = func(val int) OptionServerSet {
|
||||
return func(c *ServerConfiguration) {
|
||||
c.MaxRequestBodySize = val
|
||||
}
|
||||
}
|
||||
|
||||
// Per-connection buffer size for requests' reading.
|
||||
// This also limits the maximum header size.
|
||||
//
|
||||
// Increase this buffer if your clients send multi-KB RequestURIs
|
||||
// and/or multi-KB headers (for example, BIG cookies).
|
||||
//
|
||||
// Default buffer size is used if not set.
|
||||
OptionServerReadBufferSize = func(val int) OptionServerSet {
|
||||
return func(c *ServerConfiguration) {
|
||||
c.ReadBufferSize = val
|
||||
}
|
||||
}
|
||||
|
||||
// Per-connection buffer size for responses' writing.
|
||||
//
|
||||
// Default buffer size is used if not set.
|
||||
OptionServerWriteBufferSize = func(val int) OptionServerSet {
|
||||
return func(c *ServerConfiguration) {
|
||||
c.WriteBufferSize = val
|
||||
}
|
||||
}
|
||||
|
||||
// Maximum duration for reading the full request (including body).
|
||||
//
|
||||
// This also limits the maximum duration for idle keep-alive
|
||||
// connections.
|
||||
//
|
||||
// By default request read timeout is unlimited.
|
||||
OptionServerReadTimeout = func(val time.Duration) OptionServerSet {
|
||||
return func(c *ServerConfiguration) {
|
||||
c.ReadTimeout = val
|
||||
}
|
||||
}
|
||||
|
||||
// Maximum duration for writing the full response (including body).
|
||||
//
|
||||
// By default response write timeout is unlimited.
|
||||
OptionServerWriteTimeout = func(val time.Duration) OptionServerSet {
|
||||
return func(c *ServerConfiguration) {
|
||||
c.WriteTimeout = val
|
||||
}
|
||||
}
|
||||
|
||||
// RedirectTo, defaults to empty, set it in order to override the station's handler and redirect all requests to this address which is of form(HOST:PORT or :PORT)
|
||||
//
|
||||
// NOTE: the http status is 'StatusMovedPermanently', means one-time-redirect(the browser remembers the new addr and goes to the new address without need to request something from this server
|
||||
// which means that if you want to change this address you have to clear your browser's cache in order this to be able to change to the new addr.
|
||||
//
|
||||
// example: https://github.com/iris-contrib/examples/tree/master/multiserver_listening2
|
||||
OptionServerRedirectTo = func(val string) OptionServerSet {
|
||||
return func(c *ServerConfiguration) {
|
||||
c.RedirectTo = val
|
||||
}
|
||||
}
|
||||
|
||||
// OptionServerVirtual If this server is not really listens to a real host, it mostly used in order to achieve testing without system modifications
|
||||
OptionServerVirtual = func(val bool) OptionServerSet {
|
||||
return func(c *ServerConfiguration) {
|
||||
c.Virtual = val
|
||||
}
|
||||
}
|
||||
// OptionServerVListeningAddr, can be used for both virtual = true or false,
|
||||
// if it's setted to not empty, then the server's Host() will return this addr instead of the ListeningAddr.
|
||||
// server's Host() is used inside global template helper funcs
|
||||
// set it when you are sure you know what it does.
|
||||
//
|
||||
// Default is empty ""
|
||||
OptionServerVListeningAddr = func(val string) OptionServerSet {
|
||||
return func(c *ServerConfiguration) {
|
||||
c.VListeningAddr = val
|
||||
}
|
||||
}
|
||||
|
||||
// OptionServerVScheme if setted to not empty value then all template's helper funcs prepends that as the url scheme instead of the real scheme
|
||||
// server's .Scheme returns VScheme if not empty && differs from real scheme
|
||||
//
|
||||
// Default is empty ""
|
||||
OptionServerVScheme = func(val string) OptionServerSet {
|
||||
return func(c *ServerConfiguration) {
|
||||
c.VScheme = val
|
||||
}
|
||||
}
|
||||
|
||||
// OptionServerName the server's name, defaults to "iris".
|
||||
// You're free to change it, but I will trust you to don't, this is the only setting whose somebody, like me, can see if iris web framework is used
|
||||
OptionServerName = func(val string) OptionServerSet {
|
||||
return func(c *ServerConfiguration) {
|
||||
c.ListeningAddr = val
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// ServerParseAddr parses the listening addr and returns this
|
||||
func ServerParseAddr(listeningAddr string) string {
|
||||
// check if addr has :port, if not do it +:80 ,we need the hostname for many cases
|
||||
a := listeningAddr
|
||||
if a == "" {
|
||||
// check for os environments
|
||||
if oshost := os.Getenv("HOST"); oshost != "" {
|
||||
a = oshost
|
||||
} else if oshost := os.Getenv("ADDR"); oshost != "" {
|
||||
a = oshost
|
||||
} else if osport := os.Getenv("PORT"); osport != "" {
|
||||
a = ":" + osport
|
||||
}
|
||||
|
||||
if a == "" {
|
||||
a = DefaultServerAddr
|
||||
}
|
||||
|
||||
}
|
||||
if portIdx := strings.IndexByte(a, ':'); portIdx == 0 {
|
||||
// if contains only :port ,then the : is the first letter, so we dont have setted a hostname, lets set it
|
||||
a = DefaultServerHostname + a
|
||||
}
|
||||
if portIdx := strings.IndexByte(a, ':'); portIdx < 0 {
|
||||
// missing port part, add it
|
||||
a = a + ":80"
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
// Default values for base Server conf
|
||||
const (
|
||||
// DefaultServerHostname returns the default hostname which is 0.0.0.0
|
||||
DefaultServerHostname = "0.0.0.0"
|
||||
// DefaultServerPort returns the default port which is 8080
|
||||
DefaultServerPort = 8080
|
||||
// DefaultMaxRequestBodySize is 8MB
|
||||
DefaultMaxRequestBodySize = 2 * fasthttp.DefaultMaxRequestBodySize
|
||||
|
||||
// Per-connection buffer size for requests' reading.
|
||||
// This also limits the maximum header size.
|
||||
//
|
||||
// Increase this buffer if your clients send multi-KB RequestURIs
|
||||
// and/or multi-KB headers (for example, BIG cookies).
|
||||
//
|
||||
// Default buffer size is 8MB
|
||||
DefaultReadBufferSize = 8096
|
||||
|
||||
// Per-connection buffer size for responses' writing.
|
||||
//
|
||||
// Default buffer size is 8MB
|
||||
DefaultWriteBufferSize = 8096
|
||||
|
||||
// DefaultServerName the response header of the 'Server' value when writes to the client
|
||||
DefaultServerName = "iris"
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultServerAddr the default server addr which is: 0.0.0.0:8080
|
||||
DefaultServerAddr = DefaultServerHostname + ":" + strconv.Itoa(DefaultServerPort)
|
||||
)
|
||||
|
||||
// DefaultServerConfiguration returns the default configs for the server
|
||||
func DefaultServerConfiguration() ServerConfiguration {
|
||||
return ServerConfiguration{
|
||||
ListeningAddr: DefaultServerAddr,
|
||||
Name: DefaultServerName,
|
||||
MaxRequestBodySize: DefaultMaxRequestBodySize,
|
||||
ReadBufferSize: DefaultReadBufferSize,
|
||||
WriteBufferSize: DefaultWriteBufferSize,
|
||||
RedirectTo: "",
|
||||
Virtual: false,
|
||||
VListeningAddr: "",
|
||||
VScheme: "",
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user