63

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.

Shudipta Sharma
  • 3,469
  • 1
  • 13
  • 26
GGG
  • 737
  • 1
  • 5
  • 11
  • `(*w).Header().Set("Access-Control-Allow-Origin", req.Header.Get("Origin"))` – mkopriva Nov 14 '18 at 11:06
  • @mkopriva does not work( – GGG Nov 14 '18 at 11:46
  • Please refer to this post for answer nd how to solve this problem https://stackoverflow.com/questions/53528643/cross-origin-resource-sharing-cors-in-angular-or-angular-6-problem-while-you/53528644#53528644 – Ramesh Roddam Nov 28 '18 at 22:10
  • Hi Ramesh that link may not be the one you meant to paste it seems to be your response for a question relating to spring and the framework's particular CrossOrigin filters. For what it is worth, I think for this question if you are seeing the prefilght request but it is griping about not having ok status then from my experience you either have another error that is happening prior to the response, or OPTIONS is not an allowed verb. – Chris Wood Dec 02 '19 at 08:59

8 Answers8

43

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, Access-Control-Allow-Headers, 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.

threeve
  • 2,776
  • 25
  • 33
  • seems like the gorillamux CORS middleware is broken – Madeo Mar 17 '21 at 03:39
  • @Madeo What gives you that impression? I actually link to gorilla/handlers, not gorilla/mux anyway... – threeve Mar 17 '21 at 12:00
  • because with the Gorillamux middleware and the headers set was not working, however with the code you showed it was. I just ended up building my own middleware (10 lines of code) and remove the Gorillamux one – Madeo Mar 17 '21 at 13:23
19

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.

Ryan Shillington
  • 15,463
  • 10
  • 75
  • 85
  • Actually, going to the Network tab will tell you nothing. The GET apparently succeeds even though the Console tab says that there is a cross-origin-header error. That's explained in [this answer](https://stackoverflow.com/a/46738706/1309582). – clayRay Mar 12 '20 at 08:56
  • I think you're looking at the OPTIONS request, not the GET request. There should be 2 requests in Chrome's Network tab for every GET request you do in your code. – Ryan Shillington Jun 19 '20 at 16:33
8

Enable cross-origin requests in ASP.NET Web API click for more info

Enable CORS in the WebService app. First, add the CORS NuGet package. In Visual Studio, from the Tools menu, select NuGet Package Manager, then select Package Manager Console. In the Package Manager Console window, type the following command:

Install-Package Microsoft.AspNet.WebApi.Cors

This command installs the latest package and updates all dependencies, including the core Web API libraries. Use the -Version flag to target a specific version. The CORS package requires Web API 2.0 or later.

Open the file App_Start/WebApiConfig.cs. Add the following code to the WebApiConfig.Register method:

using System.Web.Http;
namespace WebService
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // New code
            config.EnableCors();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
}

Next, add the [EnableCors] attribute to your controller/ controller methods

using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Cors;

namespace WebService.Controllers
{
    [EnableCors(origins: "http://mywebclient.azurewebsites.net", headers: "*", methods: "*")]
    public class TestController : ApiController
    {
        // Controller methods not shown...
    }
}

Enable Cross-Origin Requests (CORS) in ASP.NET Core

Usman Mahmood
  • 197
  • 1
  • 3
4

The CORS issue should be fixed in the backend. Temporary workaround uses this option.

  1. Go to C:\Program Files\Google\Chrome\Application

  2. Open command prompt

  3. Execute the command chrome.exe --disable-web-security --user-data-dir="c:/ChromeDevSession"

Using the above option, you can able to open new chrome without security. this chrome will not throw any cors issue.

enter image description here

Sathia
  • 2,184
  • 2
  • 20
  • 37
3

Angular and Django Rest Framework.

I encountered similar error while making post request to my DRF api. It happened that all I was missing was trailing slash for endpoint.

7guyo
  • 1,358
  • 13
  • 23
2

The provided solution here is correct. However, the same error can also occur from a user error, where your endpoint request method is NOT matching the method your using when making the request.

For example, the server endpoint is defined with "RequestMethod.PUT" while you are requesting the method as POST.

JAD
  • 722
  • 7
  • 12
0

The only thing that worked for me was creating a new application in the IIS, mapping it to exactly the same physical path, and changing only the authentication to be Anonymous.

Oranit Dar
  • 1,023
  • 12
  • 13
0

For anyone looking at this and had no result with adding the Access-Control-Allow-Origin try also adding the Access-Control-Allow-Headers. May safe somebody from a headache.

e11en
  • 138
  • 2
  • 13