We encountered a very weird behavior when using Nginx as a reverse proxy.
We have REST services that need to be used with the browser, We configured these HTTP Golang
services to handle CORS
using cors package.
We noticed that when the browser triggers a preflight request the request doesn't go to the backend service and instead Nginx responds with the status 405 Method Not Allowed
and the request is never forwarded or proxied to the backend service at all.
To fix this issue we had to handle OPTIONS
requests manually from the location
directive, This is very limited as we need the liberty to update for example the allowed headers using Access-Control-Allow-Headers
based on the requested route.
How can we forward any Preflight
or OPTIONS
request to the backend to handle?
NOTE: We are using default Nginx configurations according to the official Nginx docker image.
file: main.go
package main
import (
"net/http"
"github.com/rs/cors"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello World"))
})
r := cors.AllowAll().Handler(mux)
http.ListenAndServe(":3000", r)
}
file: server.conf
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://localhost:3000;
# Handling OPTIONS for this location directive.
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin "$http_origin";
add_header Access-Control-Allow-Credentials 'true';
add_header Access-Control-Allow-Headers 'Authorization, Content-Type, Origin, X-Requested-With, Accept';
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS, PUT, DELETE';
add_header Content-Type 'text/plain; charset=utf-8';
return 204;
}
proxy_set_header X-Original-URI $request_uri;
proxy_set_header X-Original-Remote-Addr $remote_addr;
proxy_set_header X-Original-Host $host;
}
}
Related: