Documentation
¶
Index ¶
- func RejectNUL() echo.MiddlewareFunc
- func Start(ctx context.Context, e *echo.Echo, log zerolog.Logger, port string, ...)
- type Option
- func WithAllowedOrigins(origins ...string) Option
- func WithBodyLimit(limit int64) Option
- func WithCredentialedCORS() Option
- func WithIdleTimeout(d time.Duration) Option
- func WithReadHeaderTimeout(d time.Duration) Option
- func WithReadTimeout(d time.Duration) Option
- func WithWriteTimeout(d time.Duration) Option
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func RejectNUL ¶ added in v1.26.1
func RejectNUL() echo.MiddlewareFunc
RejectNUL refuses, with 400 ez.EINVALID and before any handler runs, a request that carries a NUL byte (0x00) where a handler would read it. Postgres cannot store a NUL byte in text, varchar or jsonb, and bun v1.3.0 refuses to render a string holding one into SQL, so such a string would fail its query with a 500 (ez.EINTERNAL); no legitimate client sends one.
It checks four places, in order:
- the path parameters, as c.Param returns them;
- the keys and values of the query string;
- a JSON body (media type application/json, or one ending in +json): a raw NUL byte, or the escape \u0000 when its backslash is not itself escaped. The six-character text \u0000, written "\\u0000" in JSON, passes;
- a form body (application/x-www-form-urlencoded or multipart/form-data): the keys and values of its fields and the names of its files. File contents are not inspected, since files such as images hold NUL bytes.
Media types match in any letter case, as net/http's form parsing does. The body is chosen by Content-Type, not by how the handler reads it, so a JSON body a handler reads raw, such as a webhook whose signature it checks over the bytes, is scanned and refused before the handler runs. An app that must accept such a payload on a route exempts the route by wrapping the middleware with a check on c.Path(), or by registering it on route groups instead of with e.Use. XML bodies are not checked, since encoding/xml already rejects a NUL byte, and nor are other content types. Headers need no check: net/http refuses a header holding a NUL byte before Echo runs.
It reads a JSON, urlencoded or multipart body of up to 32 MB into memory (two to three times that while reading and parsing) and puts it back, so handlers can still bind, read or stream it; a larger body passes through uninspected and intact, so it holds at most 32 MB per request whatever the body limit. Registered with e.Use it runs on every route, matched or not. Register it after CORS, so a preflight is answered first and its 400 carries the CORS headers; after any request-decompression middleware, since compressed bytes hold NUL bytes; and after a body limit such as middleware.BodyLimit, so a body over the limit gets the limit's 413 without being read first. A chunked body over the limit is read up to the limit, and the limit's error then goes to Echo's HTTPErrorHandler as Echo's own error, which Echo's default handler answers with its status.
A refusal is logged at warn level as "Request Error" with the method and the route path, never the URI, query or body. The middleware writes the 400 itself, in the handler.ErrorResponse shape with an empty request_id since no handler has created its request yet, so neither an app ErrorTranslator nor Echo's HTTPErrorHandler sees it.
func Start ¶
Start configures logging, recovery, CORS, the body limit, RejectNUL and server timeouts on e and serves on port. It always sets a 10s read-header timeout and a 120s idle timeout. The read and write timeouts are unset (unlimited) unless WithReadTimeout or WithWriteTimeout is passed.
Start blocks until ctx ends, then stops accepting connections, waits up to 10s for the requests in flight, closes the connections of any still running and returns. The caller owns the shutdown: signal.NotifyContext for SIGINT and SIGTERM gives the usual behaviour, and closing the database or flushing logs comes after Start returns. A handler still running at that point has lost its connection, so its reads and writes fail and c.Request().Context() ends once net/http notices, but it runs on until it returns or its own timeout ends (the context requests.New builds does not derive from the connection's and ends after 15s by default), so it can hit what the caller tears down.
With a ctx that has already ended Start returns at once. If the server cannot listen or fails while serving, Start logs the error at fatal level and exits the process.
The request log and Echo's own lines are written at info level and above whatever level log has, as lecho did, so a logger set to warn still logs requests.
Without WithAllowedOrigins every origin is allowed, and without WithBodyLimit request bodies are unbounded, so production callers should pass both. Start also registers RejectNUL unconditionally, after CORS and the body limit; see RejectNUL for what it inspects and its memory use.
Types ¶
type Option ¶ added in v1.16.0
type Option func(*config)
Option configures Start.
func WithAllowedOrigins ¶ added in v1.16.0
WithAllowedOrigins restricts CORS to the given origins. Without it, with no origins, or with "*" among them, every origin is allowed, and the other origins are neither used nor checked. An origin is a scheme and host with an optional port, like "https://app.example.com", matched whole ignoring case and sent back to the browser as written, so write it in lowercase as browsers send it. A pattern such as "https://*.example.com" matches nothing. An empty or padded origin (as from splitting an unset or spaced variable), one without a scheme, or one with a path, trailing slash, non-empty query or fragment makes Start panic.
func WithBodyLimit ¶ added in v1.16.0
WithBodyLimit caps request bodies at limit bytes using echo's BodyLimit middleware, e.g. 10 << 20 for 10 MiB. Larger bodies get 413. Without it, or with a zero or negative limit, bodies are unbounded.
func WithCredentialedCORS ¶ added in v1.18.0
func WithCredentialedCORS() Option
WithCredentialedCORS sends Access-Control-Allow-Credentials: true, so a browser app on another origin can send and receive cookies. It is needed for cookie-based session auth from another origin. It only takes effect together with WithAllowedOrigins naming the origins: browsers reject credentials with a wildcard origin, so without allowed origins, or with "*" among them, it is ignored and Start logs a warning. The cookie path also needs the origin checks of requests.WithCookie (the CSRF rule in docs/auth.md), since CORS alone does not stop cross-site writes.
func WithIdleTimeout ¶ added in v1.16.0
WithIdleTimeout overrides the default 120s keep-alive idle timeout.
func WithReadHeaderTimeout ¶ added in v1.16.0
WithReadHeaderTimeout overrides the default 10s read-header timeout.
func WithReadTimeout ¶ added in v1.17.0
WithReadTimeout caps the time to read a whole request, headers and body, so a client trickling body bytes cannot hold a connection open. It is off by default (zero means unlimited). Uploads that take longer than d are cut off, so size it for the slowest upload the service accepts.
func WithWriteTimeout ¶ added in v1.17.0
WithWriteTimeout caps the time from the end of reading the request headers to the end of writing the response. It is off by default (zero means unlimited). Long-running handlers, large downloads and streaming or SSE responses that take longer than d are cut off, so only set it on services that do none of those.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package generator derives an OpenAPI 3.0 document from the source of an Echo application built on compose's rest handlers.
|
Package generator derives an OpenAPI 3.0 document from the source of an Echo application built on compose's rest handlers. |
|
Package reference renders an OpenAPI 3.x document as a self-hosted API reference page: an alternative to Scalar and Redoc that ships inside the backend, with no CDN assets.
|
Package reference renders an OpenAPI 3.x document as a self-hosted API reference page: an alternative to Scalar and Redoc that ships inside the backend, with no CDN assets. |