I have created trip server. It works fine and we are able to make POST
request by Insomnia but when we make POST
request by axios on our front-end, it sends an error:
has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: It does not have HTTP ok status.
Our request on axios:
let config = { headers: { "Content-Type": "application/json", 'Access-Control-Allow-Origin': '*', } } let data = { "id": 4 } axios.post('http://196.121.147.69:9777/twirp/route.FRoute/GetLists', data, config) .then((res) => { console.log(res) }) .catch((err) => { console.log(err) }); }
My go file:
func setupResponse(w *http.ResponseWriter, req *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, X-CSRF-Token, Authorization") } func WithUserAgent(base http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() ua := r.Header.Get("Jwt") ctx = context.WithValue(ctx, "jwt", ua) r = r.WithContext(ctx) setupResponse(&w, r) base.ServeHTTP(w, r) }) } const ( host = "localhost" port = 5432 user = "postgres" password = "postgres" dbname = "postgres" ) func main() { psqlInfo := fmt.Sprintf("host=%s port=%d user=%s "+ "password=%s dbname=%s sslmode=disable", host, port, user, password, dbname) server := &s.Server{psqlInfo} twirpHandler := p.NewFinanceServiceServer(server, nil) wrap := WithUserAgent(twirpHandler) log.Fatalln(http.ListenAndServe(":9707", wrap)) }
As I said before on Insomnia it works great, but when we make an axios POST
request, on browser's console following appears:
has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: It does not have HTTP ok status.
If the server is under your control, add the origin of the requesting site to the set of domains permitted access by adding it to the Access-Control-Allow-Origin header's value. You can also configure a site to allow any site to access it by using the * wildcard. You should only use this for public APIs.
How Access to XMLHttpRequest has been blocked by CORS policy Redirect is not allowed for a preflight request only one route Error Occurs ? Just Disable CORS policy security. Go to google extension and search for Allow-Control-Allow-Origin. Now add it to chrome and enable.
Access-Control-Allow-Methods is a header request that allows one or more HTTP methods when accessing a resource when responding to a preflight request. Access-Control-Allow-Methods shows permitted HTTP methods while accessing resources.
I believe this is the simplest example:
header := w.Header() header.Add("Access-Control-Allow-Origin", "*") header.Add("Access-Control-Allow-Methods", "DELETE, POST, GET, OPTIONS") header.Add("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With")
You can also add a header for Access-Control-Max-Age
and of course you can allow any headers and methods that you wish.
Finally you want to respond to the initial request:
if r.Method == "OPTIONS" { w.WriteHeader(http.StatusOK) return }
Edit (June 2019): We now use gorilla for this. Their stuff is more actively maintained and they have been doing this for a really long time. Leaving the link to the old one, just in case.
Old Middleware Recommendation below: Of course it would probably be easier to just use middleware for this. I don't think I've used it, but this one seems to come highly recommended.
This answer explains what's going on behind the scenes, and the basics of how to solve this problem in any language. For reference, see the MDN docs on this topic.
You are making a request for a URL from JavaScript running on one domain (say domain-a.com) to an API running on another domain (domain-b.com). When you do that, the browser has to ask domain-b.com if it's okay to allow requests from domain-a.com. It does that with an HTTP OPTIONS
request. Then, in the response, the server on domain-b.com has to give (at least) the following HTTP headers that say "Yeah, that's okay":
HTTP/1.1 204 No Content // or 200 OK Access-Control-Allow-Origin: https://domain-a.com // or * for allowing anybody Access-Control-Allow-Methods: POST, GET, OPTIONS // What kind of methods are allowed ... // other headers
If you're in Chrome, you can see what the response looks like by pressing F12 and going to the "Network" tab to see the response the server on domain-b.com is giving.
So, back to the bare minimum from @threeve's original answer:
header := w.Header() header.Add("Access-Control-Allow-Origin", "*") if r.Method == "OPTIONS" { w.WriteHeader(http.StatusOK) return }
This will allow anybody from anywhere to access this data. The other headers he's included are necessary for other reasons, but these headers are the bare minimum to get past the CORS (Cross Origin Resource Sharing) requirements.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With