Documentation
¶
Overview ¶
Package cors provides configurable Cross-Origin Resource Sharing (CORS) middleware for the express framework. It sets the appropriate Access-Control-* response headers and answers CORS preflight (OPTIONS) requests with a 204 No Content response. It is the Go analogue of the ubiquitous Express cors package (expressjs/cors), packaged as a drop-in express.Handler.
Use this middleware whenever a browser-based client hosted on one origin must call an API served from another origin. The same-origin policy blocks such requests by default; CORS is the mechanism by which the server opts specific origins back in and tells the browser which methods, request headers, and response headers are permitted, and whether credentials (cookies, Authorization headers) may be sent. Typical deployments mount it globally with app.Use so both the simple requests and the preflight probes for every route are handled, but it can equally guard a single router or path prefix.
Operationally the middleware runs near the front of the chain. On every request it reads the Origin request header and, via resolveOrigin, decides whether that origin is permitted; when it is, it writes Access-Control-Allow-Origin (adding a Vary: Origin header whenever the value is a concrete origin rather than "*", so shared caches do not leak one origin's response to another). It then conditionally emits Access-Control-Allow-Credentials and Access-Control-Expose-Headers. If the request method is OPTIONS the middleware treats it as a preflight: it writes Access-Control-Allow-Methods, reflects or sets Access-Control-Allow-Headers, optionally sets Access-Control-Max-Age, sets Content-Length: 0, and short-circuits with a 204 No Content — next() is never called. For all other methods the middleware sets its headers and calls next() so the route handler runs normally.
Behavior is driven by Options, whose zero value is usable and yields an open policy: AllowedOrigins defaults to []string{"*"} (any origin) and AllowedMethods defaults to GET, HEAD, PUT, PATCH, POST, DELETE. AllowedHeaders, when empty, causes the incoming Access-Control-Request-Headers value to be reflected back verbatim (and Vary: Access-Control-Request-Headers to be set). ExposedHeaders populates Access-Control-Expose-Headers. MaxAge sets the preflight cache lifetime in seconds; a non-positive value omits the header. The important edge case concerns credentials: the CORS specification forbids combining a wildcard origin with credentials, so when AllowCredentials is true and the resolved origin would be "*", the request's concrete Origin is echoed instead. An origin that is not in the allow-list simply receives no Access-Control-Allow-Origin header — the request is not rejected server-side; the browser enforces the policy by refusing the response.
Compared with the Node original, this port keeps the same header-setting and preflight-terminating semantics and the same permissive defaults, but is intentionally leaner. It does not support per-request dynamic origin functions, regular-expression origin matching, the configurable preflightContinue / optionsSuccessStatus knobs, or custom preflight status codes; preflight always ends with 204. Origin matching is a case-insensitive exact comparison against the configured list (or an unconditional match on "*"), with no pattern support.
Example ¶
Example configures the CORS middleware with an explicit allow-list and drives it with net/http/httptest. It first issues a normal GET request carrying an allowed Origin and shows that the route handler runs and the Access-Control-Allow-Origin header is set to the concrete origin. It then issues an OPTIONS preflight request and shows that the middleware short-circuits with 204 No Content and advertises the permitted methods without invoking the route handler. Everything here is deterministic, so the expected output is asserted below.
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"github.com/malcolmston/express"
"github.com/malcolmston/express/middleware/cors"
)
func main() {
app := express.New()
app.Use(cors.New(cors.Options{
AllowedOrigins: []string{"https://app.example.com"},
AllowedMethods: []string{"GET", "POST"},
MaxAge: 600,
}))
app.Get("/", func(req *express.Request, res *express.Response, next express.Next) {
res.Send("ok")
})
// A simple cross-origin GET from an allowed origin.
get := httptest.NewRecorder()
greq := httptest.NewRequest(http.MethodGet, "/", nil)
greq.Header.Set("Origin", "https://app.example.com")
app.ServeHTTP(get, greq)
fmt.Println("GET status:", get.Code)
fmt.Println("GET allow-origin:", get.Header().Get("Access-Control-Allow-Origin"))
fmt.Println("GET body:", get.Body.String())
// A preflight OPTIONS request is answered with 204 and no handler run.
pre := httptest.NewRecorder()
preq := httptest.NewRequest(http.MethodOptions, "/", nil)
preq.Header.Set("Origin", "https://app.example.com")
app.ServeHTTP(pre, preq)
fmt.Println("preflight status:", pre.Code)
fmt.Println("preflight allow-methods:", pre.Header().Get("Access-Control-Allow-Methods"))
}
Output: GET status: 200 GET allow-origin: https://app.example.com GET body: ok preflight status: 204 preflight allow-methods: GET, POST
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Options ¶
type Options struct {
// AllowedOrigins is the list of origins permitted to make cross-origin
// requests. The special value "*" allows any origin. When empty it
// defaults to []string{"*"}.
AllowedOrigins []string
// AllowedMethods is the list of HTTP methods advertised in preflight
// responses. When empty a sensible default set is used.
AllowedMethods []string
// AllowedHeaders is the list of request headers advertised in preflight
// responses. When empty the value of the incoming
// Access-Control-Request-Headers is reflected back.
AllowedHeaders []string
// ExposedHeaders is the list of response headers exposed to the browser
// via Access-Control-Expose-Headers.
ExposedHeaders []string
// AllowCredentials, when true, adds Access-Control-Allow-Credentials: true.
// It cannot be combined with a wildcard origin; when credentials are
// enabled the request's Origin is echoed instead.
AllowCredentials bool
// MaxAge is the number of seconds a preflight response may be cached. A
// non-positive value omits the Access-Control-Max-Age header.
MaxAge int
}
Options configures the CORS middleware. The zero value is usable and behaves as an open policy that allows any origin ("*") with the default set of methods.