An experimental CORS middleware library for Go.
Unless you're a big fan of functional options, you should use github.com/jub0bs/cors instead.
- About CORS
- Design philosophy
- Praise for fcors
- Installation
- Example
- Documentation
- Code coverage
- License
The Same-Origin Policy (SOP) is a security mechanism that Web browsers implement to protect their users. In particular, the SOP restricts cross-origin network access in terms of both sending and reading. Cross-Origin Resource Sharing (CORS) is a protocol that lets servers instruct browsers to relax those restrictions for select clients.
jub0bs/fcors allows you to configure and build net/http middleware that implement CORS.
jub0bs/fcors is designed to be both easier to use and harder to misuse than other CORS middleware libraries; see Fearless CORS: a design philosophy for CORS middleware libraries (and a Go implementation) and Useful Functional-Options Tricks for Better Libraries (GopherCon Europe 2023).
I really like the declarative API. It lets you say what behavior you want rather than setting specific headers. It means that, as a user, you don’t have to relearn the nuances of CORS every time you want to make a change.
Paul Carleton (Staff Software Engineer at Stripe)
go get github.com/jub0bs/fcors
jub0bs/fcors requires Go 1.21 or above.
The following program demonstrates how to create a CORS middleware that
- allows anonymous access from Web origin
https://example.com
, - with requests whose method is either
GET
orPOST
, - and (optionally) with request header
Authorization
,
and how to apply the middleware in question to all the resources accessible
under some /api/
path:
package main
import (
"io"
"log"
"net/http"
"github.com/jub0bs/fcors"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /hello", handleHello) // note: not configured for CORS
// create CORS middleware
cors, err := fcors.AllowAccess(
fcors.FromOrigins("https://example.com"),
fcors.WithMethods(http.MethodGet, http.MethodPost),
fcors.WithRequestHeaders("Authorization"),
)
if err != nil {
log.Fatal(err)
}
api := http.NewServeMux()
api.HandleFunc("GET /users", handleUsersGet)
api.HandleFunc("POST /users", handleUsersPost)
mux.Handle("/api/", http.StripPrefix("/api", cors(api))) // note: method-less pattern here
log.Fatal(http.ListenAndServe(":8080", mux))
}
func handleHello(w http.ResponseWriter, _ *http.Request) {
io.WriteString(w, "Hello, World!")
}
func handleUsersGet(w http.ResponseWriter, _ *http.Request) {
// omitted
}
func handleUsersPost(w http.ResponseWriter, _ *http.Request) {
// omitted
}
Try it out yourself by saving this program to a file named server.go
.
You may need to adjust the port number if port 8080 happens to be unavailable
on your machine. Then build and run your server:
go build server.go
./server
If no error occurred, the server is now running on localhost:8080
and the
various resources accessible under the /api/
path are now configured for
CORS as desired.
The documentation is available on pkg.go.dev.
All source code is covered by the MIT License.