Skip to content
/ cors Public

jub0bs/cors

jub0bs/cors

tag Go Version Go Reference license build codecov goreport

An opinionated CORS middleware library for Go, designed to be both easier to use and harder to misuse than existing alternatives.

About CORS

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.

Features

This library allows you to configure and build net/http middleware that implement CORS. It distinguishes itself from other CORS middleware libraries by providing the following features:

Installation

go get github.com/jub0bs/cors

This library requires Go 1.25.0 or above. Per the Go release policy, it only supports the two most recent major releases of Go, i.e. 1.25 and 1.24.

Example

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 or POST (or HEAD), and
  • (optionally) with request header Authorization,

and how to apply the middleware in question to all the resources accessible under the /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
  cors, 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)
  }
  cors.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", cors.Wrap(api))) // note: method-less pattern here

  if err := http.ListenAndServe(":8080", mux); err != http.ErrServerClosed {
    log.Fatal(err)
  }
}

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.

If you need to handle CORS-configuration errors programmatically, see package cfgerrors.

Documentation

The documentation is available on pkg.go.dev.

Code coverage

coverage

License

All source code is covered by the MIT License.

FAQ

Is this library more performant than rs/cors is?

Yes, at least according to recent results of my microbenchmarks.

Can I use this library in conjunction with a third-party router?

The answer depends on which router you intend to use; for guidance, see jub0bs/cors-examples.

What if I need more flexibility in how I specify allowed origins?

For security, this library only supports a restricted set of origin patterns. If you need more flexibility, either fork this library or rely on another CORS middleware library, such as rs/cors. But do bear in mind that excessive flexibility in this regard implies security risks.

Besides, if you need to update the set of origins allowed by your CORS middleware, be aware that you can reconfigure it on the fly.

Can I selectively apply CORS on the basis of some URL query parameter(s)?

No.

Can I configure a CORS middleware to log a message for every single request it processes?

No, for good reasons. If you really need to do that, either wrap your CORS middleware in a logging middleware, or rely on a different CORS middleware library, such as rs/cors.

Besides, if you need to troubleshoot CORS-preflight failures, you should temporarily activate your CORS middleware's debug mode.

Can I specify a custom status code to indicate preflight success?

The Fetch standard stipulates that any status code in the 200-299 range is acceptable to indicate preflight success. Unfortunately, some (altogether rare) non-compliant clients fail CORS preflight if responses to CORS-preflight requests use a status code other than 200.

For simplicity and in compliance with the Fetch standard, this library invariably uses status code 204 to indicate preflight success. If you need to specify a custom status code to indicate preflight success, either fork this library or rely on another CORS middleware library, such as rs/cors.

I want to write tests that check CORS behavior. What should I know?

You shouldn't need to write such tests, as this library has an extensive test suite. But if you insist on writing such tests, be aware that, for performance reasons, CORS middleware produced by this library closely adheres to guarantees (provided by the Fetch standard) about the format of some CORS headers. In particular, if you wish to write tests that exercise CORS middleware via CORS-preflight requests that include an Access-Control-Request-Headers header, keep in mind that you should specify the comma-separated elements in that header value

  • in lower case,
  • in lexicographical order,
  • without repetitions.

Otherwise, the CORS middleware will cause preflight to fail.

What should I do if I wish to configure intermediaries so they cache responses to CORS-preflight requests?

See the penultimate bullet point in the package's doc comment.

Additional resources

About

perhaps the best CORS middleware library for Go

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project

 

Packages

 
 
 

Contributors

Languages