How to enable OPTIONS requests globally?

I am using HTTP handlers in 1.22, however, OPTIONS requests are automatically being rejected and a 405 sent to the client. For this reason, I am unable to call any POST endpoints from my SPA application. Is there a way to automatically allow OPTIONS requests globally without using third party tools/libraries?

I do it this way:

	switch r.Method {
	case "GET":
		Read(w, r)
	case "DELETE":
		Delete(w, r)
	case "POST":
		Create(w, r)
	case "PUT":
		Update(w, r)
	case "OPTIONS":
		// bugfix (handshake)
		Read(w, r)

You should be able to just use something like this:

func newAppMux() *http.ServeMux {
	router := http.NewServeMux()
	// Global options handler
	router.HandleFunc("OPTIONS /", handleOptions)
	return router

func handleOptions(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Access-Control-Allow-Origin", "")
	w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
	w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, Authorization")

A note about β€œ/” in the pattern. From the docs:

The special wildcard {$} matches only the end of the URL. For example, the pattern β€œ/{$}” matches only the path β€œ/”, whereas the pattern β€œ/” matches every path.

So that matches every path for that method (β€œOPTIONS”). For further reading on CORS and understanding of what headers you might want to set, check this out.

1 Like

There is no need to declare a global OPTIONS handler for CORS, though; and rather than implementing CORS by hand, which is error-prone, I’d recommend using a dedicated library. Here is an example:

package main

import (


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{""},
    Methods:        []string{http.MethodGet, http.MethodPost},
    RequestHeaders: []string{"Authorization"},
  if err != nil {
  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(w http.ResponseWriter, _ *http.Request) {
  // omitted

func handleUsersPost(w http.ResponseWriter, _ *http.Request) {
  // omitted