Elasticsearch: Problems with http.cors.allow-methods

Created on 1 Apr 2016  ·  4Comments  ·  Source: elastic/elasticsearch

Elasticsearch version: 2.3.0
JVM version: 1.8.0_31
OS version: MAC OS X 10.10.5
Description of the problem including expected versus actual behavior:
Definition of an accepted a custom header does not seem to work.

Steps to reproduce:

  1. Add the following lines to the configuration file
http.cors.enabled: true
http.cors.allow-origin: "*"
http.cors.allow-methods: OPTIONS, HEAD, GET, POST, PUT, DELETE
http.cors.allow-headers: "X-Requested-With, Content-Type, Content-Length, X-User"
  1. Ran an ajax POST request with X-User header.
  2. Getting response "Request header field x-user is not allowed by Access-Control-Allow-Headers in preflight response."
:CorInfrREST API >bug v2.3.1 v5.0.0-alpha2

Most helpful comment

  • The problem appears to be in NettyHttpServerTransport.buildCorsConfig() where first parameter to the getAsArray() function should be the setting name and not the value of the setting.
  • It affects cors-allow-headers as well.
  • It's also specific to 2.3 branch as the whole settings system seems to have been reworked on master.

The following code

        String[] strMethods = settings.getAsArray(settings.get(SETTING_CORS_ALLOW_METHODS, DEFAULT_CORS_METHODS), new String[0]);
        HttpMethod[] methods = new HttpMethod[strMethods.length];
        for (int i = 0; i < methods.length; i++) {
            methods[i] = HttpMethod.valueOf(strMethods[i]);
        }
        return builder.allowedRequestMethods(methods)
                      .maxAge(settings.getAsInt(SETTING_CORS_MAX_AGE, DEFAULT_CORS_MAX_AGE))
                      .allowedRequestHeaders(settings.getAsArray(settings.get(SETTING_CORS_ALLOW_HEADERS, DEFAULT_CORS_HEADERS), new String[0]))
                      .shortCircuit()
                      .build();

should say

        String[] strMethods = settings.getAsArray(SETTING_CORS_ALLOW_METHODS, DEFAULT_CORS_METHODS);
        HttpMethod[] methods = new HttpMethod[strMethods.length];
        for (int i = 0; i < methods.length; i++) {
            methods[i] = HttpMethod.valueOf(strMethods[i]);
        }
        return builder.allowedRequestMethods(methods)
                      .maxAge(settings.getAsInt(SETTING_CORS_MAX_AGE, DEFAULT_CORS_MAX_AGE))
                      .allowedRequestHeaders(settings.getAsArray(SETTING_CORS_ALLOW_HEADERS, DEFAULT_CORS_HEADERS))
                      .shortCircuit()
                      .build();

All 4 comments

I am afraid I will need to reopen this.

Elasticsearch version: 2.3.0
JVM version: 1.8.0_31
OS version: MAC OS X 10.10.5

Use of custom header does not seem to work reliably.

Here is the CORS section of my configuration (elasticsearch.yml) file:

http.cors.enabled: true
http.cors.allow-origin: "*"
http.cors.allow-headers: "X-Requested-With, Content-Type, Content-Length, X-User"

The client code is performing the following call:

jQuery.ajax({
    url: requrl,
    data: reqdata,
    type: 'POST',
    headers: {"X-User": user},
    success: function (result, status, xhr) {
        resolve(result);
    },
    error: function (xhr, status, error) {
        reject(error);
    }
});

Now, that request always goes through with Firefox 45.0.1.
However, it does not work for:

  • Safari Version 9.1 (10601.5.17.4)
  • Chrome Version 49.0.2623.110 (64-bit)

When inspecting with Chrome I get:

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

These are the headers details I see in Chrome:

General
-----------
Request URL:http://localhost:9200/myindex/mytype/_search
Request Method:OPTIONS
Status Code:200 OK
Remote Address:[::1]:9200

Response Headers
--------------------------
Access-Control-Allow-Methods:
Access-Control-Allow-Origin:*
Access-Control-Max-Age:1728000
content-length:0
date:Mon, 04 Apr 2016 13:49:00 GMT

Request Headers
-----------------------
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8,it;q=0.6
Access-Control-Request-Headers:accept, content-type, x-user
Access-Control-Request-Method:POST
Cache-Control:no-cache
Connection:keep-alive
Host:localhost:9200
Origin:http://localhost:3333
Pragma:no-cache
Referer:http://localhost:3333/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36

The very same configuration, index and client code works reliably in 2.2.0.
After seeing in the release notes the entry: “More robust handling of CORS HTTP Access Control” I am wondering if that has anything to do with it.

I have experienced same issue which now breaks Grafana UI.

  • The problem appears to be in NettyHttpServerTransport.buildCorsConfig() where first parameter to the getAsArray() function should be the setting name and not the value of the setting.
  • It affects cors-allow-headers as well.
  • It's also specific to 2.3 branch as the whole settings system seems to have been reworked on master.

The following code

        String[] strMethods = settings.getAsArray(settings.get(SETTING_CORS_ALLOW_METHODS, DEFAULT_CORS_METHODS), new String[0]);
        HttpMethod[] methods = new HttpMethod[strMethods.length];
        for (int i = 0; i < methods.length; i++) {
            methods[i] = HttpMethod.valueOf(strMethods[i]);
        }
        return builder.allowedRequestMethods(methods)
                      .maxAge(settings.getAsInt(SETTING_CORS_MAX_AGE, DEFAULT_CORS_MAX_AGE))
                      .allowedRequestHeaders(settings.getAsArray(settings.get(SETTING_CORS_ALLOW_HEADERS, DEFAULT_CORS_HEADERS), new String[0]))
                      .shortCircuit()
                      .build();

should say

        String[] strMethods = settings.getAsArray(SETTING_CORS_ALLOW_METHODS, DEFAULT_CORS_METHODS);
        HttpMethod[] methods = new HttpMethod[strMethods.length];
        for (int i = 0; i < methods.length; i++) {
            methods[i] = HttpMethod.valueOf(strMethods[i]);
        }
        return builder.allowedRequestMethods(methods)
                      .maxAge(settings.getAsInt(SETTING_CORS_MAX_AGE, DEFAULT_CORS_MAX_AGE))
                      .allowedRequestHeaders(settings.getAsArray(SETTING_CORS_ALLOW_HEADERS, DEFAULT_CORS_HEADERS))
                      .shortCircuit()
                      .build();

Thank you for reporting the issue. We have PRs open to fix them for different versions.

17523 #17524 #17525

Was this page helpful?
0 / 5 - 0 ratings