Search code examples
angulargocorsgorilla

CORS Error: It does not have HTTP ok status. GoLang Mux API


I'm trying to make http requests via Angular 17 App. And everytime the browser responds:

Access to XMLHttpRequest at 'http://localhost:8082/login' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

In my angular-interceptor is passing this header:

@Injectable()
export class HttpInterceptor implements HttpInterceptor {
  constructor(private router: Router,
                private authService: AuthService) {
    }

    intercept(req: HttpRequest<any>, nextHandler: HttpHandler): Observable<HttpEvent<any>> {
        const authToken = StorageUtil.getAuthToken();
        let request = req.clone({
            setHeaders: {
                "Content-Type": "application/json",
                'Access-Control-Allow-Origin': '*',
            }
        });
        if (authToken == null || authToken == "") {
            this.router.navigate(['/auth/login']).then(() => {
                return throwError(() => new Error('Você precisa estar logado'));
            });
        }
        if (authToken != null && StorageUtil.isTokenExpired()) {
            this.authService.refreshToken().subscribe((resp) => {
                const accestoken = resp.data.accessToken as string;
                request = request.clone({
                    setHeaders: {
                        Authorization: `Bearer ${accestoken}`
                    }
                });
                return nextHandler.handle(request);
            })
        }
        request = request.clone({
            setHeaders: {
                Authorization: `Bearer ${authToken}`
            }
        });
        return nextHandler.handle(request);
    }
}

And my gorilla/mux Go API I pass this middleware to every handler in the server:

func jsonContentTypeMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        //Enable CORS
        w.Header().Set("Content-Type", "application/json")
        w.Header().Set("Access-Control-Allow-Origin", "*")
        w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, DELETE")
        w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With")
        next.ServeHTTP(w, r)
    })
}
func main(){
router := app.newRouter() //create my router with gorila/mux 
startServer(jsonContentTypeMiddleware(router))

}
func startServer(handler http.Handler) {
    fmt.Printf("API rodando na porta: %s", webPort)
    s := &http.Server{
        Addr:         fmt.Sprintf("%s:%s", host, webPort),
        Handler:      handler,
        WriteTimeout: time.Hour,
        ReadTimeout:  time.Hour,
    }
    log.Fatal(s.ListenAndServe())
}

Solution

  • As you've come to realise, "manually" implementing CORS is error-prone. You're better off relying on some existing CORS middleware library; you'll find one solution using my own library below.

    Besides, with Go v1.22's addition of enhanced routing patterns, the need for third-party routers like gorilla/mux is moot; you can get by with the standard library's net/http package.

    package main
    
    import (
        "io"
        "log"
        "net/http"
    
        "github.com/jub0bs/cors"
    )
    
    func main() {
        mux := http.NewServeMux()
        mux.HandleFunc("GET /hello", handleHello)
    
        corsMiddleware, err := cors.NewMiddleware(cors.Config{
            Origins: []string{"*"},
            Methods: []string{
                http.MethodGet,
                http.MethodPost,
                http.MethodPut,
                http.MethodDelete,
            },
            RequestHeaders: []string{
                "Authorization",
                "Content-Type",
                "X-Requested-With",
            },
        })
        if err != nil {
            log.Fatal(err)
        }
        s := &http.Server{
            Addr:    "localhost:8080",
            Handler: corsMiddleware.Wrap(mux),
            // other settings omitted
        }
        log.Fatal(s.ListenAndServe())
    }
    
    func handleHello(w http.ResponseWriter, _ *http.Request) {
        w.Header().Set("Content-Type", "application/json")
        io.WriteString(w, `{"msg": "Hello, World!"}`)
    }