'Can perform POST call from browser using go-swagger and gorilla mux
I am using gorilla/mux and go-swagger to serve REST endpoints. Since I am running goswagger and calling REST endpoints from browser, the POST call is making http.MethodOptions first and then http.MethodPut later. Because of which I had a lot of extra code for http.MethodOptions and doing practically nothing on my application. I am guess this can be avoided but I couldn't find an example. If I delete http.MethodOptions from the code the rest call if failing from browser although CURL request succeed from terminal.
package rest
func Middleware(handler http.Handler) http.Handler {
log.Println("middleware registered")
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Println("REST URI:", r.RequestURI, r.Method)
w.Header().Add("Access-Control-Allow-Origin", "*")
w.Header().Add("Content-Type", "application/json, multipart/form-data")
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, X-CSRF-Token, Authorization")
handler.ServeHTTP(w, r)
})
}
func ListenAndServe(pathPrefix, addr string) error {
// router := mux.NewRouter()
// router.Use(Middleware)
apiRouter := mux.NewRouter().PathPrefix(pathPrefix).Subrouter()
apiRouter.Use(Middleware)
// register product route
{
// apiRouter.Path("/").Handler(http.HandlerFunc(handlers.Products)).Methods()
apiRouter.HandleFunc("/product", handlers.Products).Methods(http.MethodGet, http.MethodPost, http.MethodOptions)
apiRouter.HandleFunc("/product/{id}", handlers.Product).Methods(http.MethodGet, http.MethodPut, http.MethodDelete, http.MethodOptions)
}
// register container route
{
containerRouter := apiRouter.PathPrefix("/container").Subrouter()
containerRouter.HandleFunc("/{id}/start", handlers.containerStart).Methods(http.MethodPut, http.MethodOptions)
containerRouter.HandleFunc("/{id}/stop", handlers.containerStop).Methods(http.MethodPut, http.MethodOptions)
}
srv := &http.Server{
Addr: addr,
WriteTimeout: 15 * time.Second,
ReadTimeout: 15 * time.Second,
IdleTimeout: time.Second * 60,
Handler: apiRouter,
}
return srv.ListenAndServe()
}
And Code for Container start
package handlers
import (
"net/http"
"github.com/gorilla/mux"
)
func ContainerStart(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodOptions:
case http.MethodPut:
/*
swagger:route PUT /container/{id}/start Container startContainer
Start Container artifact
Consumes:
- application/json
Produces:
- application/json
Schemes: http
Responses:
default: genericError
200:
*/
log.Println("REST: container start")
// DO Something
}
}
Solution 1:[1]
The OPTIONS request you are seeing is called a preflight request which is part of CORS. CORS is a common obstacle which has been tackled many times, gorilla even offers pre-built middleware.
The reason cURL works is because it doesn't implement CORS, since it is a security feature which is only really relevant to full browsers.
CORS only applies to cross-origin requests. If the site making the POST request is dedicated to this REST API, you can also bypass the issue by hosting both on the same domain(that is more complicated to host), but this depends on your senario.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Dylan Reimerink |
