A principled CORS middleware library for Go, designed to be both easier to use and harder to misuse than existing alternatives.
The Same-Origin Policy (SOP) is a security mechanism that Web browsers implement to protect their users. In particular, the SOP places some restrictions on 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.
This package allows you to configure and build net/http middleware that implement CORS.
go get github.com/jub0bs/cors
jub0bs/cors requires Go 1.23 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/cors"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /hello", handleHello) // note: not configured for CORS
// create CORS middleware
corsMw, err := cors.NewMiddleware(cors.Config{
Origins: []string{"https://example.com"},
Methods: []string{http.MethodGet, http.MethodPost},
RequestHeaders: []string{"Authorization"},
})
if err != nil {
log.Fatal(err)
}
corsMw.SetDebug(true) // turn debug mode on (optional)
api := http.NewServeMux()
api.HandleFunc("GET /users", handleUsersGet)
api.HandleFunc("POST /users", handleUsersPost)
mux.Handle("/api/", http.StripPrefix("/api", corsMw.Wrap(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(_ http.ResponseWriter, _ *http.Request) {
// omitted
}
func handleUsersPost(_ 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.
Moreover, guidance on how to use jub0bs/cors with popular third-party routers can be found in jub0bs/cors-examples.
Some benchmarks pitting jub0bs/cors against rs/cors are available in jub0bs/cors-benchmarks.
All source code is covered by the MIT License.
- Fearless CORS: a design philosophy for CORS middleware libraries (and a Go implementation) (blog post)
- jub0bs/cors: a better CORS middleware library for Go (blog post)
- Reconfigurable CORS middleware with jub0bs/cors (blog post)
- Useful Functional-Options Tricks for Better Libraries (GopherCon Europe 2023) (video)
- github.com/jub0bs/fcors (this library's predecessor)
Despite all of jub0bs/cors's goodness, you may still have valid reasons for sticking with rs/cors, at least for the time being. Here is as exhaustive a list as I could come up with:
- You cannot yet migrate to Go v1.22 (whose semantics are assumed by jub0bs/cors).
- You need more flexibility than that offered by jub0bs/cors's origin patterns; but do bear in mind that excessive flexibility in this regard implies security risks.
- You want to log a message for every single request processed by your CORS middleware; but do you, really?