Back to godoc.org
github.com/aofei/air

Package air

v0.20.0
Latest Go to latest

The latest major version is .

Published: 2 days ago | License: MIT | Module: github.com/aofei/air

Overview

Package air implements an ideally refined web framework for Go.

Router

A router is basically the most important component of a web framework. In this framework, registering a route usually requires at least two params:

air.Default.GET(
	"/users/:UserID/posts/:PostID/assets/*",
	func(req *air.Request, res *air.Response) error {
		userID, err := req.Param("UserID").Value().Int64()
		if err != nil {
			return err
		}

		postID, err := req.Param("PostID").Value().Int64()
		if err != nil {
			return err
		}

		assetPath := req.Param("*").Value().String()

		return res.WriteJSON(map[string]interface{}{
			"user_id":    userID,
			"post_id":    postID,
			"asset_path": assetPath,
		})
	},
)

The first param is a route path that contains 6 components. Among them, "users", "posts" and "assets" are STATIC components, ":UserID" and ":PostID" are PARAM components, "*" is an ANY component. Note that all route params (PARAM and ANY components) will be parsed into the `Request` and can be accessed via the `Request.Param` and `Request.Params`. The name of a `RequestParam` parsed from a PARAM component always discards its leading ":", such as ":UserID" will become "UserID". The name of a `RequestParam` parsed from an ANY component is "*".

The second param is a `Handler` that serves the requests that match this route.

Index

Variables

var Default = New()

Default is the default instance of the `Air`.

If you only need one instance of the `Air`, you should use the `Default`. Unless you think you can efficiently pass your instance in different scopes.

func DefaultErrorHandler

func DefaultErrorHandler(err error, req *Request, res *Response)

DefaultErrorHandler is the default centralized error handler.

func DefaultMethodNotAllowedHandler

func DefaultMethodNotAllowedHandler(req *Request, res *Response) error

DefaultMethodNotAllowedHandler is the default `Handler` that returns method not allowed error.

func DefaultNotFoundHandler

func DefaultNotFoundHandler(req *Request, res *Response) error

DefaultNotFoundHandler is the default `Handler` that returns not found error.

type Air

type Air struct {
	// AppName is the name of the web application.
	//
	// It is recommended to set the `AppName` and try to ensure that it is
	// unique (used to distinguish between different web applications).
	//
	// Default value: "air"
	AppName string `mapstructure:"app_name"`

	// MaintainerEmail is the e-mail address of the one who is responsible
	// for maintaining the web application.
	//
	// It is recommended to set the `MaintainerEmail` if the `ACMEEnabled`
	// is true (used by the CAs, such as Let's Encrypt, to notify about
	// problems with issued certificates).
	//
	// Default value: ""
	MaintainerEmail string `mapstructure:"maintainer_email"`

	// DebugMode indicates whether the web application is in debug mode.
	//
	// Please keep in mind that the `DebugMode` is quite bossy, some
	// features will be affected if it is true. So never set the `DebugMode`
	// to true in a production environment unless you want to do something
	// crazy.
	//
	// Default value: false
	DebugMode bool `mapstructure:"debug_mode"`

	// Address is the TCP address that the server listens on.
	//
	// The `Address` is never empty and contains a free port. If the port of
	// the `Address` is "0", a random port is automatically chosen. The
	// `Addresses` can be used to discover the chosen port.
	//
	// Default value: "localhost:8080"
	Address string `mapstructure:"address"`

	// ReadTimeout is the maximum duration allowed for the server to read a
	// request entirely, including the body part.
	//
	// The `ReadTimeout` does not let the `Handler` make per-request
	// decisions on each request body's acceptable deadline or upload rate.
	//
	// Default value: 0
	ReadTimeout time.Duration `mapstructure:"read_timeout"`

	// ReadHeaderTimeout is the maximum duration allowed for the server to
	// read the headers of a request.
	//
	// The connection's read deadline is reset after reading the headers of
	// a request and the `Handler` can decide what is considered too slow
	// for the body.
	//
	// If the `ReadHeaderTimeout` is zero, the value of the `ReadTimeout` is
	// used. If both are zero, there is no timeout.
	//
	// Default value: 0
	ReadHeaderTimeout time.Duration `mapstructure:"read_header_timeout"`

	// WriteTimeout is the maximum duration allowed for the server to write
	// a response.
	//
	// The `WriteTimeout` is reset whenever the headers of a new request are
	// read. Like the `ReadTimeout`, the `WriteTimeout` does not let the
	// `Handler` make decisions on a per-request basis.
	//
	// Default value: 0
	WriteTimeout time.Duration `mapstructure:"write_timeout"`

	// IdleTimeout is the maximum duration allowed for the server to wait
	// for the next request.
	//
	// If the `IdleTimeout` is zero, the value of the `ReadTimeout` is used.
	// If both are zero, there is no timeout.
	//
	// Default value: 0
	IdleTimeout time.Duration `mapstructure:"idle_timeout"`

	// MaxHeaderBytes is the maximum number of bytes allowed for the server
	// to read parsing the request headers' names and values, including
	// HTTP/1.x request-line.
	//
	// Default value: 1048576
	MaxHeaderBytes int `mapstructure:"max_header_bytes"`

	// TLSConfig is the TLS configuration to make the server to handle
	// requests on incoming TLS connections.
	//
	// Default value: nil
	TLSConfig *tls.Config `mapstructure:"-"`

	// TLSCertFile is the path to the TLS certificate file.
	//
	// The `TLSCertFile` must be set together wth the `TLSKeyFile`.
	//
	// If the certificate targeted by the `TLSCertFile` is signed by a CA,
	// it should be the concatenation of the certificate, any intermediates,
	// and the CA's certificate.
	//
	// If the `TLSConfig` is not nil, the certificate targeted by the
	// `TLSCertFile` will be appended to the end of the `Certificates` of
	// the `TLSConfig`'s clone. Otherwise, a new instance of the
	// `tls.Config` will be created with the certificate.
	//
	// Default value: ""
	TLSCertFile string `mapstructure:"tls_cert_file"`

	// TLSKeyFile is the path to the TLS key file.
	//
	// The key targeted by the `TLSKeyFile` must match the certificate
	// targeted by the `TLSCertFile`.
	//
	// Default value: ""
	TLSKeyFile string `mapstructure:"tls_key_file"`

	// ACMEEnabled indicates whether the ACME feature is enabled.
	//
	// The `ACMEEnabled` gives the server the ability to automatically
	// obtain new certificates from the ACME CA.
	//
	// If the `TLSConfig` and `TLSConfig.GetCertificate` are not nil, the
	// server will respect it and use the ACME feature as a backup.
	// Otherwise, a new instance of the `tls.Config` will be created with
	// the ACME feature.
	//
	// Default value: false
	ACMEEnabled bool `mapstructure:"acme_enabled"`

	// ACMEDirectoryURL is the ACME CA directory URL of the ACME feature.
	//
	// Default value: "https://acme-v02.api.letsencrypt.org/directory"
	ACMEDirectoryURL string `mapstructure:"acme_directory_url"`

	// ACMETOSURLWhitelist is the list of ACME CA's Terms of Service (TOS)
	// URL allowed by the ACME feature.
	//
	// If the length of the `ACMETOSURLWhitelist` is zero, all TOS URLs will
	// be allowed.
	//
	// Default value: nil
	ACMETOSURLWhitelist []string `mapstructure:"acme_tos_url_whitelist"`

	// ACMEAccountKey is the account key of the ACME feature used to
	// register with an ACME CA and sign requests.
	//
	// Supported algorithms:
	//   * RS256
	//   * ES256
	//   * ES384
	//   * ES512
	//
	// If the `ACMEAccountKey` is nil, a new ECDSA P-256 key is generated.
	//
	// Default value: nil
	ACMEAccountKey crypto.Signer `mapstructure:"-"`

	// ACMECertRoot is the root of the certificates of the ACME feature.
	//
	// It is recommended to set the `ACMECertRoot` since all ACME CAs have a
	// rate limit on issuing certificates. Different web applications can
	// share the same place (if they are all built using this framework).
	//
	// Default value: "acme-certs"
	ACMECertRoot string `mapstructure:"acme_cert_root"`

	// ACMEHostWhitelist is the list of hosts allowed by the ACME feature.
	//
	// It is highly recommended to set the `ACMEHostWhitelist`. If the
	// length of the `ACMEHostWhitelist` is not zero, all connections that
	// are not connected to the hosts in it will not be able to obtain new
	// certificates from the ACME CA.
	//
	// Default value: nil
	ACMEHostWhitelist []string `mapstructure:"acme_host_whitelist"`

	// ACMERenewalWindow is the renewal window of the ACME feature before a
	// certificate expires.
	//
	// Default value: 2592000000000000
	ACMERenewalWindow time.Duration `mapstructure:"acme_renewal_window"`

	// ACMEExtraExts is the list of extra extensions used when generating a
	// new CSR (Certificate Request), thus allowing customization of the
	// resulting certificate.
	//
	// Default value: nil
	ACMEExtraExts []pkix.Extension `mapstructure:"-"`

	// HTTPSEnforced indicates whether the server is forcibly accessible
	// only via the HTTPS scheme (HTTP requests will be automatically
	// redirected to HTTPS).
	//
	// The `HTTPSEnforced` will always be treated as true when the
	// `ACMEEnabled` is true.
	//
	// Default value: false
	HTTPSEnforced bool `mapstructure:"https_enforced"`

	// HTTPSEnforcedPort is the port of the TCP address (share the same host
	// as the `Address`) that the server listens on. All requests to this
	// port will be automatically redirected to HTTPS.
	//
	// If the `HTTPSEnforcedPort` is "0", a random port is automatically
	// chosen. The `Addresses` can be used to discover the chosen port.
	//
	// Default value: "0"
	HTTPSEnforcedPort string `mapstructure:"https_enforced_port"`

	// WebSocketHandshakeTimeout is the maximum duration allowed for the
	// server to wait for a WebSocket handshake to complete.
	//
	// Default value: 0
	WebSocketHandshakeTimeout time.Duration `mapstructure:"websocket_handshake_timeout"`

	// WebSocketSubprotocols is the list of supported WebSocket subprotocols
	// of the server.
	//
	// If the length of the `WebSocketSubprotocols` is not zero, the
	// `Response.WebSocket` negotiates a subprotocol by selecting the first
	// match with a protocol requested by the client. If there is no match,
	// no protocol is negotiated (the Sec-Websocket-Protocol header is not
	// included in the handshake response).
	//
	// Default value: nil
	WebSocketSubprotocols []string `mapstructure:"websocket_subprotocols"`

	// PROXYEnabled indicates whether the PROXY feature is enabled.
	//
	// The `PROXYEnabled` gives the server the ability to support the PROXY
	// protocol (See
	// https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt).
	//
	// Default value: false
	PROXYEnabled bool `mapstructure:"proxy_enabled"`

	// PROXYReadHeaderTimeout is the maximum duration allowed for the server
	// to read the PROXY protocol header of a connection.
	//
	// The connection's read deadline is reset after reading the PROXY
	// protocol header.
	//
	// Default value: 0
	PROXYReadHeaderTimeout time.Duration `mapstructure:"proxy_read_header_timeout"`

	// PROXYRelayerIPWhitelist is the list of IP addresses or CIDR notation
	// IP address ranges of the relayers allowed by the PROXY feature.
	//
	// It is highly recommended to set the `PROXYRelayerIPWhitelist`. If the
	// length of the `PROXYRelayerIPWhitelist` is not zero, all connections
	// relayed from the IP addresses are not in it will not be able to act
	// the PROXY protocol.
	//
	// Default value: nil
	PROXYRelayerIPWhitelist []string `mapstructure:"proxy_relayer_ip_whitelist"`

	// Pregases is the `Gas` chain stack that performs before routing.
	//
	// The `Pregases` is always FILO.
	//
	// Default value: nil
	Pregases []Gas `mapstructure:"-"`

	// Gases is the `Gas` chain stack that performs after routing.
	//
	// The `Gases` is always FILO.
	//
	// Default value: nil
	Gases []Gas `mapstructure:"-"`

	// NotFoundHandler is the `Handler` that returns not found error.
	//
	// The `NotFoundHandler` is never nil because the router will use it as
	// the default `Handler` when no match is found.
	//
	// Default value: `DefaultNotFoundHandler`
	NotFoundHandler func(*Request, *Response) error `mapstructure:"-"`

	// MethodNotAllowedHandler is the `Handler` that returns method not
	// allowed error.
	//
	// The `MethodNotAllowedHandler` is never nil because the router will
	// use it as the default `Handler` when a match is found but the request
	// method is not registered.
	//
	// Default value: `DefaultMethodNotAllowedHandler`
	MethodNotAllowedHandler func(*Request, *Response) error `mapstructure:"-"`

	// ErrorHandler is the centralized error handler.
	//
	// The `ErrorHandler` is never nil because the server will use it in
	// every request-response cycle that has an error.
	//
	// Default value: `DefaultErrorHandler`
	ErrorHandler func(error, *Request, *Response) `mapstructure:"-"`

	// ErrorLogger is the `log.Logger` that logs errors that occur in the
	// web application.
	//
	// If the `ErrorLogger` is nil, logging is done via the log package's
	// standard logger.
	//
	// Default value: nil
	ErrorLogger *log.Logger `mapstructure:"-"`

	// RendererTemplateRoot is the root of the HTML templates of the
	// renderer feature.
	//
	// All HTML template files inside the `RendererTemplateRoot` will be
	// recursively parsed into the renderer and their names will be used as
	// HTML template names.
	//
	// Default value: "templates"
	RendererTemplateRoot string `mapstructure:"renderer_template_root"`

	// RendererTemplateExts is the list of filename extensions of the HTML
	// templates of the renderer feature used to distinguish the HTML
	// template files in the `RendererTemplateRoot`.
	//
	// Default value: [".html"]
	RendererTemplateExts []string `mapstructure:"renderer_template_exts"`

	// RendererTemplateLeftDelim is the left side of the HTML template
	// delimiter of the renderer feature.
	//
	// default value: "{{"
	RendererTemplateLeftDelim string `mapstructure:"renderer_template_left_delim"`

	// RendererTemplateRightDelim is the right side of the HTML template
	// delimiter of the renderer feature.
	//
	// Default value: "}}"
	RendererTemplateRightDelim string `mapstructure:"renderer_template_right_delim"`

	// RendererTemplateFuncMap is the HTML template function map of the
	// renderer feature.
	//
	// The HTML template functions described in
	// https://pkg.go.dev/text/template#hdr-Functions and the following are
	// always available:
	//  * strlen
	//      Returns the number of characters of its argument.
	//  * substr
	//      Returns the substring consisting of the characters of its first
	//      argument starting at a start index (the second argument) and
	//      continuing up to, but not including, the character at an end
	//      index (the third argument).
	//  * timefmt
	//      Returns a textual representation of its first argument for the
	//      time layout (the second argument).
	//  * locstr
	//      Returns a localized string for its argument. It works exactly
	//      the same as the `Request.LocalizedString`
	//
	// Default value: nil
	RendererTemplateFuncMap template.FuncMap `mapstructure:"-"`

	// MinifierEnabled indicates whether the minifier feature is enabled.
	//
	// The `MinifierEnabled` gives the `Response.Write` the ability to
	// minify the matching response body on the fly based on the
	// Content-Type header.
	//
	// Default value: false
	MinifierEnabled bool `mapstructure:"minifier_enabled"`

	// MinifierMIMETypes is the list of MIME types of the minifier feature
	// that will trigger the minimization.
	//
	// Supported MIME types:
	//   * text/html
	//   * text/css
	//   * application/javascript
	//   * application/json
	//   * application/xml
	//   * image/svg+xml
	//
	// Unsupported MIME types will be silently ignored.
	//
	// Default value: ["text/html", "text/css", "application/javascript",
	// "application/json", "application/xml", "image/svg+xml"]
	MinifierMIMETypes []string `mapstructure:"minifier_mime_types"`

	// GzipEnabled indicates whether the gzip feature is enabled.
	//
	// The `GzipEnabled` gives the `Response` the ability to gzip the
	// matching response body on the fly based on the Content-Type header.
	//
	// Default value: false
	GzipEnabled bool `mapstructure:"gzip_enabled"`

	// GzipMIMETypes is the list of MIME types of the gzip feature that will
	// trigger the gzip.
	//
	// Default value: ["text/plain", "text/html", "text/css",
	// "application/javascript", "application/json", "application/xml",
	// "application/toml", "application/yaml", "image/svg+xml"]
	GzipMIMETypes []string `mapstructure:"gzip_mime_types"`

	// GzipCompressionLevel is the compression level of the gzip feature.
	//
	// Default value: `gzip.DefaultCompression`
	GzipCompressionLevel int `mapstructure:"gzip_compression_level"`

	// GzipMinContentLength is the minimum content length of the gzip
	// featrue used to limit at least how big (determined only from the
	// Content-Length header) response body can be gzipped.
	//
	// Default value: 1024
	GzipMinContentLength int64 `mapstructure:"gzip_min_content_length"`

	// CofferEnabled indicates whether the coffer feature is enabled.
	//
	// The `CofferEnabled` gives the `Response.WriteFile` the ability to use
	// the runtime memory to reduce the disk I/O pressure.
	//
	// Default value: false
	CofferEnabled bool `mapstructure:"coffer_enabled"`

	// CofferMaxMemoryBytes is the maximum number of bytes of the runtime
	// memory allowed for the coffer feature to use.
	//
	// Default value: 33554432
	CofferMaxMemoryBytes int `mapstructure:"coffer_max_memory_bytes"`

	// CofferAssetRoot is the root of the assets of the coffer feature.
	//
	// All asset files inside the `CofferAssetRoot` will be recursively
	// parsed into the coffer and their names will be used as asset names.
	//
	// Default value: "assets"
	CofferAssetRoot string `mapstructure:"coffer_asset_root"`

	// CofferAssetExts is the list of filename extensions of the assets of
	// the coffer feature used to distinguish the asset files in the
	// `CofferAssetRoot`.
	//
	// Default value: [".html", ".css", ".js", ".json", ".xml", ".toml",
	// ".yaml", ".yml", ".svg", ".jpg", ".jpeg", ".png", ".gif"]
	CofferAssetExts []string `mapstructure:"coffer_asset_exts"`

	// I18nEnabled indicates whether the i18n feature is enabled.
	//
	// The `I18nEnabled` gives the `Request.LocalizedString` and
	// `Response.Render` the ability to adapt to the request's favorite
	// conventions based on the Accept-Language header.
	//
	// Default value: false
	I18nEnabled bool `mapstructure:"i18n_enabled"`

	// I18nLocaleRoot is the root of the locales of the i18n feature.
	//
	// All TOML-based locale files (".toml" is the extension) inside the
	// `I18nLocaleRoot` will be parsed into the i18n and their names
	// (without extension) will be used as locales.
	//
	// Default value: "locales"
	I18nLocaleRoot string `mapstructure:"i18n_locale_root"`

	// I18nLocaleBase is the base of the locales of the i18n feature used
	// when a locale cannot be found.
	//
	// Default value: "en-US"
	I18nLocaleBase string `mapstructure:"i18n_locale_base"`

	// ConfigFile is the path to the configuration file that will be parsed
	// into the matching fields before starting the server.
	//
	// The ".json" extension means the configuration file is JSON-based.
	//
	// The ".toml" extension means the configuration file is TOML-based.
	//
	// The ".yaml" and ".yml" extensions means the configuration file is
	// YAML-based.
	//
	// Default value: ""
	ConfigFile string `mapstructure:"-"`
	// contains filtered or unexported fields
}

Air is the top-level struct of this framework.

It is highly recommended not to modify the value of any field of the `Air` after calling the `Air.Serve`, which will cause unpredictable problems.

The new instances of the `Air` should only be created by calling the `New`. If you only need one instance of the `Air`, it is recommended to use the `Default`, which will help you simplify the scope management.

func New

func New() *Air

New returns a new instance of the `Air` with default field values.

The `New` is the only function that creates new instances of the `Air` and keeps everything working.

func (*Air) AddShutdownJob

func (a *Air) AddShutdownJob(f func()) int

AddShutdownJob adds the f as a shutdown job that will run only once when the `Shutdown` is called. The return value is an unique ID assigned to the f, which can be used to remove the f from the shutdown job queue by calling the `RemoveShutdownJob`.

func (*Air) Addresses

func (a *Air) Addresses() []string

Addresses returns all TCP addresses that the server of the a actually listens on.

func (*Air) BATCH

func (a *Air) BATCH(methods []string, path string, h Handler, gases ...Gas)

BATCH registers a batch of routes for the methods and path with the matching h in the router of the a with the optional route-level gases.

The methods must either be nil (means all) or consists of one or more of the "GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "CONNECT", "OPTIONS" and "TRACE". Invalid methods will be silently ignored.

The path may consist of STATIC, PARAM and ANY components.

The gases is always FILO.

func (*Air) CONNECT

func (a *Air) CONNECT(path string, h Handler, gases ...Gas)

CONNECT registers a new CONNECT route for the path with the matching h in the router of the a with the optional route-level gases.

The path may consist of STATIC, PARAM and ANY components.

The gases is always FILO.

func (*Air) Close

func (a *Air) Close() error

Close closes the server of the a immediately.

func (*Air) DELETE

func (a *Air) DELETE(path string, h Handler, gases ...Gas)

DELETE registers a new DELETE route for the path with the matching h in the router of the a with the optional route-level gases.

The path may consist of STATIC, PARAM and ANY components.

The gases is always FILO.

func (*Air) FILE

func (a *Air) FILE(path, filename string, gases ...Gas)

FILE registers a new GET and HEAD route pair with the path in the router of the a to serve a static file with the filename and optional route-level gases.

The path may consist of STATIC, PARAM and ANY components.

The gases is always FILO.

func (*Air) FILES

func (a *Air) FILES(prefix, root string, gases ...Gas)

FILES registers some new GET and HEAD route paris with the path prefix in the router of the a to serve the static files from the root with the optional route-level gases.

The prefix may consit of STATIC and PARAM components, but it must not contain ANY component.

The gases is always FILO.

func (*Air) GET

func (a *Air) GET(path string, h Handler, gases ...Gas)

GET registers a new GET route for the path with the matching h in the router of the a with the optional route-level gases.

The path may consist of STATIC, PARAM and ANY components.

The gases is always FILO.

func (*Air) Group

func (a *Air) Group(prefix string, gases ...Gas) *Group

Group returns a new instance of the `Group` with the path prefix and optional group-level gases that inherited from the a.

The prefix may consit of STATIC and PARAM components, but it must not contain ANY component.

The gases is always FILO.

func (*Air) HEAD

func (a *Air) HEAD(path string, h Handler, gases ...Gas)

HEAD registers a new HEAD route for the path with the matching h in the router of the a with the optional route-level gases.

The path may consist of STATIC, PARAM and ANY components.

The gases is always FILO.

func (*Air) OPTIONS

func (a *Air) OPTIONS(path string, h Handler, gases ...Gas)

OPTIONS registers a new OPTIONS route for the path with the matching h in the router of the a with the optional route-level gases.

The path may consist of STATIC, PARAM and ANY components.

The gases is always FILO.

func (*Air) PATCH

func (a *Air) PATCH(path string, h Handler, gases ...Gas)

PATCH registers a new PATCH route for the path with the matching h in the router of the a with the optional route-level gases.

The path may consist of STATIC, PARAM and ANY components.

The gases is always FILO.

func (*Air) POST

func (a *Air) POST(path string, h Handler, gases ...Gas)

POST registers a new POST route for the path with the matching h in the router of the a with the optional route-level gases.

The path may consist of STATIC, PARAM and ANY components.

The gases is always FILO.

func (*Air) PUT

func (a *Air) PUT(path string, h Handler, gases ...Gas)

PUT registers a new PUT route for the path with the matching h in the router of the a with the optional route-level gases.

The path may consist of STATIC, PARAM and ANY components.

The gases is always FILO.

func (*Air) RemoveShutdownJob

func (a *Air) RemoveShutdownJob(id int)

RemoveShutdownJob removes the shutdown job targeted by the id from the shutdown job queue.

func (*Air) Serve

func (a *Air) Serve() error

Serve starts the server of the a.

func (*Air) ServeHTTP

func (a *Air) ServeHTTP(rw http.ResponseWriter, r *http.Request)

ServeHTTP implements the `http.Handler`.

func (*Air) Shutdown

func (a *Air) Shutdown(ctx context.Context) error

Shutdown gracefully shuts down the server of the a without interrupting any active connections. It works by first closing all open listeners, then start running all shutdown jobs added via the `AddShutdownJob` concurrently, and then closing all idle connections, and then waiting indefinitely for connections to return to idle and shutdown jobs to complete and then shut down. If the ctx expires before the shutdown is complete, it returns the context's error, otherwise it returns any error returned from closing the underlying listener(s) of the server of the a.

When the `Shutdown` is called, the `Serve` immediately return the `http.ErrServerClosed`. Make sure the program does not exit and waits instead for the `Shutdown` to return.

The `Shutdown` does not attempt to close nor wait for hijacked connections such as WebSockets. The caller should separately notify such long-lived connections of shutdown and wait for them to close, if desired. See the `AddShutdownJob` for a way to add shutdown jobs.

func (*Air) TRACE

func (a *Air) TRACE(path string, h Handler, gases ...Gas)

TRACE registers a new TRACE route for the path with the matching h in the router of the a with the optional route-level gases.

The path may consist of STATIC, PARAM and ANY components.

The gases is always FILO.

type Gas

type Gas func(Handler) Handler

Gas defines a function to process gases.

A gas is a function chained in the request-response cycle with access to the `Request` and `Response` which it uses to perform a specific action, for example, logging every request or recovering from panics.

The param is the next `Handler` that the gas will be called.

The return value is the gas that is wrapped into a `Handler`.

func WrapHTTPMiddleware

func WrapHTTPMiddleware(hm func(http.Handler) http.Handler) Gas

WrapHTTPMiddleware provides a convenient way to wrap an `http.Handler` middleware into a `Gas`.

type Group

type Group struct {
	// Air is where the group belongs.
	Air *Air

	// Prefix is the prefix of all route paths.
	//
	// All paths of routes registered by the group will share the `Prefix`.
	//
	// The `Prefix` may consit of STATIC and PARAM components, but it must
	// not contain ANY component.
	Prefix string

	// Gases is the group-level gases.
	//
	// All gases of routes registered by the group will share the `Gases`
	// at the bottom of the stack.
	//
	// The `Gases` is always FILO.
	Gases []Gas
}

Group is a set of sub-routes for a specified route. It can be used for inner routes that share common gases or functionality that should be separate from the parent while still inheriting from it.

func (*Group) BATCH

func (g *Group) BATCH(methods []string, path string, h Handler, gases ...Gas)

BATCH is just like the `Air.BATCH`.

func (*Group) CONNECT

func (g *Group) CONNECT(path string, h Handler, gases ...Gas)

CONNECT is just like the `Air.CONNECT`.

func (*Group) DELETE

func (g *Group) DELETE(path string, h Handler, gases ...Gas)

DELETE is just like the `Air.DELETE`.

func (*Group) FILE

func (g *Group) FILE(path, file string, gases ...Gas)

FILE is just like the `Air.FILE`.

func (*Group) FILES

func (g *Group) FILES(prefix, root string, gases ...Gas)

FILES is just like the `Air.FILES`.

func (*Group) GET

func (g *Group) GET(path string, h Handler, gases ...Gas)

GET is just like the `Air.GET`.

func (*Group) Group

func (g *Group) Group(prefix string, gases ...Gas) *Group

Group is just like the `Air.Group`.

func (*Group) HEAD

func (g *Group) HEAD(path string, h Handler, gases ...Gas)

HEAD is just like the `Air.HEAD`.

func (*Group) OPTIONS

func (g *Group) OPTIONS(path string, h Handler, gases ...Gas)

OPTIONS is just like the `Air.OPTIONS`.

func (*Group) PATCH

func (g *Group) PATCH(path string, h Handler, gases ...Gas)

PATCH is just like the `Air.PATCH`.

func (*Group) POST

func (g *Group) POST(path string, h Handler, gases ...Gas)

POST is just like the `Air.POST`.

func (*Group) PUT

func (g *Group) PUT(path string, h Handler, gases ...Gas)

PUT is just like the `Air.PUT`.

func (*Group) TRACE

func (g *Group) TRACE(path string, h Handler, gases ...Gas)

TRACE is just like the `Air.TRACE`.

type Handler

type Handler func(*Request, *Response) error

Handler defines a function to serve requests.

func WrapHTTPHandler

func WrapHTTPHandler(hh http.Handler) Handler

WrapHTTPHandler provides a convenient way to wrap an `http.Handler` into a `Handler`.

type Request

type Request struct {
	// Air is where the request belongs.
	Air *Air

	// Method is the method.
	//
	// See RFC 7231, section 4.3.
	//
	// For HTTP/1.x, it is from the request-line.
	//
	// For HTTP/2, it is from the ":method" pseudo-header.
	//
	// E.g.: "GET"
	Method string

	// Scheme is the scheme. It is "http" or "https".
	//
	// See RFC 3986, section 3.1.
	//
	// For HTTP/1.x, it is from the request-line.
	//
	// For HTTP/2, it is from the ":scheme" pseudo-header.
	//
	// E.g.: "http"
	Scheme string

	// Authority is the authority. It may be of the form "host:port".
	//
	// See RFC 3986, Section 3.2.
	//
	// For HTTP/1.x, it is from the Host header.
	//
	// For HTTP/2, it is from the ":authority" pseudo-header.
	//
	// E.g.: "localhost:8080"
	Authority string

	// Path is the path. It may contain the query part.
	//
	// See RFC 7540, section 8.1.2.3.
	//
	// For HTTP/1.x, it represents the request-target of the request-line.
	//
	// For HTTP/2, it represents the ":path" pseudo-header.
	//
	// E.g.: "/foo/bar?foo=bar"
	Path string

	// Header is the header map.
	//
	// See RFC 7231, section 5.
	//
	// The values of the Trailer header are the names of the trailers which
	// will come later. In this case, those names of the header map will be
	// set after reading from the `Body` returns the `io.EOF`.
	//
	// The `Header` is basically the same for both HTTP/1.x and HTTP/2. The
	// only difference is that HTTP/2 requires header names to be lowercase
	// (for aesthetic reasons, this framework decided to follow this rule
	// implicitly, so please use the header name in HTTP/1.x style).
	//
	// E.g.: {"Foo": ["bar"]}
	Header http.Header

	// Body is the message body. It will be closed by the server.
	Body io.ReadCloser

	// ContentLength records the length of the `Body`. The value -1
	// indicates that the length is unknown (it will be set after reading
	// from the `Body` returns the `io.EOF`). Values >= 0 indicate that the
	// given number of bytes may be read from the `Body`.
	ContentLength int64

	// Context is the associated context.
	//
	// The `Context` is canceled when the connection closes, the request is
	// canceled (with HTTP/2), or when the request-response cycle is
	// finished.
	Context context.Context
	// contains filtered or unexported fields
}

Request is an HTTP request.

The `Request` not only represents HTTP/1.x requests, but also represents HTTP/2 requests, and always show as HTTP/2 requests.

func (*Request) Bind

func (r *Request) Bind(v interface{}) error

Bind binds the r into the v based on the Content-Type header.

Supported MIME types:

* application/json
* application/xml
* application/protobuf
* application/msgpack
* application/toml
* application/yaml
* application/x-www-form-urlencoded
* multipart/form-data

func (*Request) ClientAddress

func (r *Request) ClientAddress() string

ClientAddress returns the original network address that sent the r.

Usually, the original network address is the same as the last network address that sent the r. But, the Forwarded and X-Forwarded-For headers will be considered, which may affect the return value.

func (*Request) ClientHost

func (r *Request) ClientHost() string

ClientHost is like the `ClientAddress`, but only returns the host part.

func (*Request) Cookie

func (r *Request) Cookie(name string) *http.Cookie

Cookie returns the matched `http.Cookie` for the name. It returns nil if not found.

func (*Request) Cookies

func (r *Request) Cookies() []*http.Cookie

Cookies returns all `http.Cookie` in the r.

func (*Request) HTTPRequest

func (r *Request) HTTPRequest() *http.Request

HTTPRequest returns the underlying `http.Request` of the r.

ATTENTION: You should never call this method unless you know what you are doing. And, be sure to call the `SetHTTPRequest` of the r when you have modified it.

func (*Request) LocalizedString

func (r *Request) LocalizedString(key string) string

LocalizedString returns a localized string for the key based on the Accept-Language header. It returns the key without any changes if the `I18nEnabled` of the `Air` of the r is false or something goes wrong.

func (*Request) Param

func (r *Request) Param(name string) *RequestParam

Param returns the matched `RequestParam` for the name. It returns nil if not found.

func (*Request) Params

func (r *Request) Params() []*RequestParam

Params returns all `RequestParam` in the r.

func (*Request) RawPath

func (r *Request) RawPath() string

RawPath returns the raw path part of the `Path`.

E.g.: "/foo/bar?foo=bar" -> "/foo/bar"

func (*Request) RawQuery

func (r *Request) RawQuery() string

RawQuery returns the raw query part (without '?') of the `Path`.

E.g.: "/foo/bar?foo=bar" -> "foo=bar"

func (*Request) RemoteAddress

func (r *Request) RemoteAddress() string

RemoteAddress returns the last network address that sent the r.

func (*Request) RemoteHost

func (r *Request) RemoteHost() string

RemoteHost is like the `RemoteAddress`, but only returns the host part.

func (*Request) SetHTTPRequest

func (r *Request) SetHTTPRequest(hr *http.Request)

SetHTTPRequest sets the hr to the underlying `http.Request` of the r.

ATTENTION: You should never call this method unless you know what you are doing.

func (*Request) SetValue

func (r *Request) SetValue(key string, value interface{})

SetValue sets the matched `interface{}` for the key from the values associated with the r to the value.

func (*Request) Value

func (r *Request) Value(key string) interface{}

Value returns the matched `interface{}` for the key from the values associated with the r. It returns nil if not found.

func (*Request) Values

func (r *Request) Values() map[string]interface{}

Values returns the values associated with the r.

Note that the returned map is always non-nil.

type RequestParam

type RequestParam struct {
	// Name is the name.
	Name string

	// Values is the values.
	//
	// Access order: route param value (always at the first) > request query
	// value(s) > request form value(s) > request multipart form value(s) >
	// request multipart form file(s).
	//
	// Note that there will always be at least one value when the request
	// param is from the `Request.Param` or `Request.Params`.
	Values []*RequestParamValue
}

RequestParam is an HTTP request param.

The param may come from the route params, request query, request form and request multipart form.

func (*RequestParam) Value

func (rp *RequestParam) Value() *RequestParamValue

Value returns the first value of the rp. It returns nil if the rp is nil or there are no values.

type RequestParamValue

type RequestParamValue struct {
	// contains filtered or unexported fields
}

RequestParamValue is an HTTP request param value.

The `RequestParamValue` may represent a route param value, request query value, request form value, request multipart form value or request multipart form file value.

func (*RequestParamValue) Bool

func (rpv *RequestParamValue) Bool() (bool, error)

Bool returns a `bool` from the underlying value of the rpv.

func (*RequestParamValue) File

func (rpv *RequestParamValue) File() (*multipart.FileHeader, error)

File returns a `multipart.FileHeader` from the underlying value of the rpv.

func (*RequestParamValue) Float32

func (rpv *RequestParamValue) Float32() (float32, error)

Float32 returns a `float32` from the underlying value of the rpv.

func (*RequestParamValue) Float64

func (rpv *RequestParamValue) Float64() (float64, error)

Float64 returns a `float64` from the underlying value of the rpv.

func (*RequestParamValue) Int

func (rpv *RequestParamValue) Int() (int, error)

Int returns an `int` from the underlying value of the rpv.

func (*RequestParamValue) Int16

func (rpv *RequestParamValue) Int16() (int16, error)

Int16 returns an `int16` from the underlying value of the rpv.

func (*RequestParamValue) Int32

func (rpv *RequestParamValue) Int32() (int32, error)

Int32 returns an `int32` from the underlying value of the rpv.

func (*RequestParamValue) Int64

func (rpv *RequestParamValue) Int64() (int64, error)

Int64 returns an `int64` from the underlying value of the rpv.

func (*RequestParamValue) Int8

func (rpv *RequestParamValue) Int8() (int8, error)

Int8 returns an `int8` from the underlying value of the rpv.

func (*RequestParamValue) String

func (rpv *RequestParamValue) String() string

String returns a `string` from the underlying value of the rpv. It returns "" if the rpv is not text-based.

func (*RequestParamValue) Uint

func (rpv *RequestParamValue) Uint() (uint, error)

Uint returns an `uint` from the underlying value of the rpv.

func (*RequestParamValue) Uint16

func (rpv *RequestParamValue) Uint16() (uint16, error)

Uint16 returns an `uint16` from the underlying value of the rpv.

func (*RequestParamValue) Uint32

func (rpv *RequestParamValue) Uint32() (uint32, error)

Uint32 returns an `uint32` from the underlying value of the rpv.

func (*RequestParamValue) Uint64

func (rpv *RequestParamValue) Uint64() (uint64, error)

Uint64 returns an `uint64` from the underlying value of the rpv.

func (*RequestParamValue) Uint8

func (rpv *RequestParamValue) Uint8() (uint8, error)

Uint8 returns an `uint8` from the underlying value of the rpv.

type Response

type Response struct {
	// Air is where the response belongs.
	Air *Air

	// Status is the status code.
	//
	// See RFC 7231, section 6.
	//
	// For HTTP/1.x, it will be put in the Response-Line.
	//
	// For HTTP/2, it will be the ":status" pseudo-header.
	//
	// E.g.: 200
	Status int

	// Header is the header map.
	//
	// See RFC 7231, section 7.
	//
	// By setting the Trailer header to the names of the trailers which will
	// come later. In this case, those names of the header map are treated
	// as if they were trailers.
	//
	// The `Header` is basically the same for both HTTP/1.x and HTTP/2. The
	// only difference is that HTTP/2 requires header names to be lowercase
	// (for aesthetic reasons, this framework decided to follow this rule
	// implicitly, so please use the header name in HTTP/1.x style).
	//
	// E.g.: {"Foo": ["bar"]}
	Header http.Header

	// Body is the message body. It can be used to write a streaming
	// response.
	Body io.Writer

	// ContentLength records the length of the `Body`. The value -1
	// indicates that the length is unknown (it will continue to increase
	// as the data written to the `Body` increases). Values >= 0 indicate
	// that the given number of bytes has been written to the `Body`.
	ContentLength int64

	// Written indicates whether at least one byte has been written to the
	// client, or the connection has been hijacked.
	Written bool

	// Minified indicates whether the `Body` has been minified.
	Minified bool

	// Gzipped indicates whether the `Body` has been gzipped.
	Gzipped bool
	// contains filtered or unexported fields
}

Response is an HTTP response.

The `Response` not only represents HTTP/1.x responses, but also represents HTTP/2 responses, and always show as HTTP/2 responses.

func (*Response) Defer

func (r *Response) Defer(f func())

Defer pushes the f onto the stack of functions that will be called after responding. Nil functions will be silently dropped.

func (*Response) Flush

func (r *Response) Flush()

Flush flushes any buffered data to the client.

The `Flush` does nothing if it is not supported by the underlying `http.ResponseWriter` of the r.

func (*Response) HTTPResponseWriter

func (r *Response) HTTPResponseWriter() http.ResponseWriter

HTTPResponseWriter returns the underlying `http.ResponseWriter` of the r.

ATTENTION: You should never call this method unless you know what you are doing. And, be sure to call the `SetHTTPResponseWriter` of the r when you have modified it.

func (*Response) ProxyPass

func (r *Response) ProxyPass(target string, rp *ReverseProxy) error

ProxyPass passes the request to the target and writes the response from the target to the client by using the reverse proxy technique. If the rp is nil, the default instance of the `ReverseProxy` will be used.

The target must be based on the HTTP protocol (such as HTTP, WebSocket and gRPC). So, the scheme of the target must be "http", "https", "ws", "wss", "grpc" or "grpcs".

func (*Response) Push

func (r *Response) Push(target string, pos *http.PushOptions) error

Push initiates an HTTP/2 server push. This constructs a synthetic request using the target and pos, serializes that request into a "PUSH_PROMISE" frame, then dispatches that request using the server's request handler. If pos is nil, default options are used.

The target must either be an absolute path (like "/path") or an absolute URL that contains a valid authority and the same scheme as the parent request. If the target is a path, it will inherit the scheme and authority of the parent request.

The `Push` returns `http.ErrNotSupported` if the client has disabled it or if it is not supported by the underlying `http.ResponseWriter` of the r.

func (*Response) Redirect

func (r *Response) Redirect(url string) error

Redirect writes the url as a redirection to the client.

The `Status` of the r will be the `http.StatusFound` if it is not a redirection status.

func (*Response) Render

func (r *Response) Render(m map[string]interface{}, templates ...string) error

Render renders one or more HTML templates with the m and writes the results as a "text/html" content to the client. The results rendered by the former can be inherited by accessing the `m["InheritedHTML"]`.

func (*Response) SetCookie

func (r *Response) SetCookie(c *http.Cookie)

SetCookie sets the c to the `Header` of the r. Invalid cookies will be silently dropped.

func (*Response) SetHTTPResponseWriter

func (r *Response) SetHTTPResponseWriter(hrw http.ResponseWriter)

SetHTTPResponseWriter sets the hrw to the underlying `http.ResponseWriter` of the r.

ATTENTION: You should never call this method unless you know what you are doing.

func (*Response) WebSocket

func (r *Response) WebSocket() (*WebSocket, error)

WebSocket switches the connection of the r to the WebSocket protocol. See RFC 6455.

func (*Response) Write

func (r *Response) Write(content io.ReadSeeker) error

Write writes the content to the client.

The main benefit of the `Write` over the `io.Copy` with the `Body` of the r is that it handles range requests properly, sets the Content-Type response header, and handles the If-Match, If-Unmodified-Since, If-None-Match, If-Modified-Since and If-Range request headers.

func (*Response) WriteFile

func (r *Response) WriteFile(filename string) error

WriteFile writes a file content targeted by the filename to the client.

func (*Response) WriteHTML

func (r *Response) WriteHTML(h string) error

WriteHTML writes the h as a "text/html" content to the client.

func (*Response) WriteJSON

func (r *Response) WriteJSON(v interface{}) error

WriteJSON writes an "application/json" content encoded from the v to the client.

func (*Response) WriteMsgpack

func (r *Response) WriteMsgpack(v interface{}) error

WriteMsgpack writes an "application/msgpack" content encoded from the v to the client.

func (*Response) WriteProtobuf

func (r *Response) WriteProtobuf(v interface{}) error

WriteProtobuf writes an "application/protobuf" content encoded from the v to the client.

func (*Response) WriteString

func (r *Response) WriteString(s string) error

WriteString writes the s as a "text/plain" content to the client.

func (*Response) WriteTOML

func (r *Response) WriteTOML(v interface{}) error

WriteTOML writes an "application/toml" content encoded from the v to the client.

func (*Response) WriteXML

func (r *Response) WriteXML(v interface{}) error

WriteXML writes an "application/xml" content encoded from the v to the client.

func (*Response) WriteYAML

func (r *Response) WriteYAML(v interface{}) error

WriteYAML writes an "application/yaml" content encoded from the v to the client.

type ReverseProxy

type ReverseProxy struct {
	// Transport is used to perform the request to the target.
	//
	// Normally the `Transport` should be nil, which means that a default
	// and well-improved one will be used. If the `Transport` is not nil, it
	// is responsible for keeping the `Response.ProxyPass` working properly.
	Transport http.RoundTripper

	// FlushInterval is the flush interval to flush to the client while
	// copying the body of the response from the target.
	//
	// If the `FlushInterval` is zero, no periodic flushing is done.
	//
	// If the `FlushInterval` is negative, copies are flushed to the client
	// immediately.
	//
	// The `FlushInterval` will always be treated as negative when the
	// response from the target is recognized as a streaming response.
	FlushInterval time.Duration

	// ModifyRequestMethod modifies the method of the request to the target.
	ModifyRequestMethod func(method string) (string, error)

	// ModifyRequestPath modifies the path of the request to the target.
	//
	// Note that the path contains the query part. Therefore, the returned
	// path must also be in this format.
	ModifyRequestPath func(path string) (string, error)

	// ModifyRequestHeader modifies the header of the request to the target.
	ModifyRequestHeader func(header http.Header) (http.Header, error)

	// ModifyRequestBody modifies the body of the request from the target.
	//
	// It is the caller's responsibility to close the returned
	// `io.ReadCloser`, which means that the `Response.ProxyPass` will be
	// responsible for closing it.
	ModifyRequestBody func(body io.ReadCloser) (io.ReadCloser, error)

	// ModifyResponseStatus modifies the status of the response from the
	// target.
	ModifyResponseStatus func(status int) (int, error)

	// ModifyResponseHeader modifies the header of the response from the
	// target.
	ModifyResponseHeader func(header http.Header) (http.Header, error)

	// ModifyResponseBody modifies the body of the response from the target.
	//
	// It is the caller's responsibility to close the returned
	// `io.ReadCloser`, which means that the `Response.ProxyPass` will be
	// responsible for closing it.
	ModifyResponseBody func(body io.ReadCloser) (io.ReadCloser, error)
}

ReverseProxy is used by the `Response.ProxyPass` to achieve the reverse proxy technique.

type WebSocket

type WebSocket struct {
	// TextHandler is the handler that handles the incoming text messages.
	TextHandler func(text string) error

	// BinaryHandler is the handler that handles the incoming binary
	// messages.
	BinaryHandler func(b []byte) error

	// ConnectionCloseHandler is the handler that handles the incoming
	// connection close messages.
	ConnectionCloseHandler func(status int, reason string) error

	// PingHandler is the handler that handles the incoming ping messages.
	PingHandler func(appData string) error

	// PongHandler is the handler that handles the incoming pong messages.
	PongHandler func(appData string) error

	// ErrorHandler is the handler that handles error occurs in the incoming
	// messages.
	ErrorHandler func(err error)

	// Closed indicates whether the connection has been closed.
	Closed bool
	// contains filtered or unexported fields
}

WebSocket is a WebSocket peer.

It is highly recommended not to modify any handlers of the `WebSocket` after calling the `WebSocket.Listen`, which will cause unpredictable problems.

func (*WebSocket) Close

func (ws *WebSocket) Close() error

Close closes the ws without sending or waiting for a close message.

func (*WebSocket) Listen

func (ws *WebSocket) Listen()

Listen listens for the messages sent from the remote peer of the ws. After one call to it, subsequent calls have no effect.

func (*WebSocket) SetMaxMessageBytes

func (ws *WebSocket) SetMaxMessageBytes(mmb int64)

SetMaxMessageBytes sets the maximum number of bytes allowed for the ws to read messages from the remote peer. If a message exceeds the limit, the ws sends a close message to the remote peer.

func (*WebSocket) SetReadDeadline

func (ws *WebSocket) SetReadDeadline(t time.Time) error

SetReadDeadline sets the read deadline on the connection of the ws. After a read has timed out, the state of the ws is corrupt and all future reads will return an error immediately.

func (*WebSocket) SetWriteDeadline

func (ws *WebSocket) SetWriteDeadline(t time.Time) error

SetWriteDeadline sets the write deadline on the connection of the ws. After a write has timed out, the state of the ws is corrupt and all future writes will return an error immediately.

func (*WebSocket) WriteBinary

func (ws *WebSocket) WriteBinary(b []byte) error

WriteBinary writes the b as a binary message to the remote peer of the ws.

func (*WebSocket) WriteConnectionClose

func (ws *WebSocket) WriteConnectionClose(status int, reason string) error

WriteConnectionClose writes a connection close message to the remote peer of the ws with the status and reason.

func (*WebSocket) WritePing

func (ws *WebSocket) WritePing(appData string) error

WritePing writes a ping message to the remote peer of the ws with the appData.

func (*WebSocket) WritePong

func (ws *WebSocket) WritePong(appData string) error

WritePong writes a pong message to the remote peer of the ws with the appData.

func (*WebSocket) WriteText

func (ws *WebSocket) WriteText(text string) error

WriteText writes the text as a text message to the remote peer of the ws.

Package Files

Documentation was rendered with GOOS=linux and GOARCH=amd64.

Jump to identifier

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to identifier