iris/configuration.go

860 lines
31 KiB
Go

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: "",
}
}