Enable CORS ElasticSearch 5.1.1

Does the configuration:

http.cors.enabled: true
http.cors.allow-origin: "*"

work for version 5.1.1?

I have these set, and verified using curl:

curl -H "User-Agent: Mozilla" -H "Origin: http://test" -i localhost:9200
HTTP/1.1 200 OK
access-control-allow-origin: *
content-type: application/json; charset=UTF-8
content-length: 327

{
"name" : "sbCcNGJ",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "fNK5M23BTCei-Pukk2mLrg",
"version" : {
"number" : "5.1.1",
"build_hash" : "5395e21",
"build_date" : "2016-12-06T12:36:15.409Z",
"build_snapshot" : false,
"lucene_version" : "6.3.0"
},
"tagline" : "You Know, for Search"
}

Yet, I always get the: Request header field Access-Control-Allow-Origin is not allowed by Access-Control-Allow-Headers in preflight response.

I am using an angularJS web app.

I've tried every setting I could find regarding this issue but they were all for previous versions of ElasticSearch.

Thanks.

Why does your preflight request contain a Access-Control-Allow-Origin header? I think that is your problem here.

That was me adding those to the request header from a thread that someone posted stating that it fixed their problem. I removed them and I get this error:

XMLHttpRequest cannot load http://localhost:9200/myIndex/_search. Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response.

My instance of ElasticSearch has it enabled:

curl -H "User-Agent: Mozilla" -H "Origin: http://test" -i localhost:9200

HTTP/1.1 200 OK
access-control-allow-origin: *
content-type: application/json; charset=UTF-8
content-length: 327

{
"name" : "sbCcNGJ",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "fNK5M23BTCei-Pukk2mLrg",
"version" : {
"number" : "5.1.1",
"build_hash" : "5395e21",
"build_date" : "2016-12-06T12:36:15.409Z",
"build_snapshot" : false,
"lucene_version" : "6.3.0"
},
"tagline" : "You Know, for Search"
}

Thanks.

It might help to explain the basics of CORS; please forgive me if this is already familiar to you.

Suppose web content on domain a.b.c wants to invoke content on domain x.y.z. The user agent (typically your browser) sends a request:

GET / HTTP/1.1
Host: x.y.z
Origin: a.b.c
<skipping a bunch of other headers>

The server responds with:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
<skipping a bunch of other headers>

<response body>

Since the server allows cross-origin requests from any origin, the request proceeds and the user agent receives a body.

Now consider a less basic request. In particular, assume the request invokes any method other than GET, HEAD, or POST, or the request is a POST with any Content-Type different than application/x-www-form-urlencoded, multipart/form-data, or text/plain, or the request contains any custom headers (by default, the only accepted headers are Accept, Accept-Language, Content-Language, and Content-Type). In this case, the user agent will first send a preflight check. This is to protect user data in case the request will be denied by the CORS policy on the server.

The user agent will send:

OPTIONS / HTTP/1.1
Host: x.y.z
Origin: a.b.c
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Authorization
<skipping a bunch of other headers>

The server will respond with:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: a.b.c
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: Authorization
Access-Control-Max-Age: 86400
<skipping a bunch of other headers>

This tells the user agent: I will accept cross-origin requests from a.b.c, only for the methods POST, GET, OPTIONS, the only custom header I will accept is Authorization, and you do not need to do another preflight check for the next 86400 seconds (24 hours).

If, say, Authorization is missing from Access-Control-Allow-Headers, you will be told in the preflight check:

Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response.

Now, going back to your original question you saw:

Request header field Access-Control-Allow-Origin is not allowed by Access-Control-Allow-Headers in preflight response.

This means that the cross-origin request contained a custom header: Access-Control-Allow-Origin: it does not make sense for the user agent to be sending that header in a cross-origin request, it's the servers job to send that back. That's why I told you this is a problem, it doesn't even make sense.

Now, let's look at your second question where you saw:

Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response.

Does your cross-origin request need to send an Authorization header? If so, you have to allow this. You can set this in Elasticsearch by adding the setting:

http.cors.allow-headers: Authorization

to your Elasticsearch configuration. Note that you might need other headers too (the default value is X-Requested-With,Content-Type,Content-Length.

I hope this helps?

3 Likes

Thanks, that is an excellent summary of CORS. I have never taken the time to dig into it.

I am doing a POST so I changed my header to "application/x-www-form-urlencoded" and it works now. I had it set to "application/json"

The strange thing is, I have other POST requests to JBoss services with the content type set to "application/json" and there is no issue.

Anyway, thanks again for the great succinct explanation.

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.