CORS: Support regular expressions for origin to match against
This commit adds regular expression support for the allow-origin header depending on the value of the request `Origin` header. The existing HttpRequestBuilder is also extended to support the OPTIONS HTTP method. Relates #5601 Closes #6891
This commit is contained in:
parent
1fb9f404df
commit
a1e335b1e9
|
@ -42,7 +42,10 @@ i.e. whether a browser on another origin can do requests to
|
||||||
Elasticsearch. Defaults to `true`.
|
Elasticsearch. Defaults to `true`.
|
||||||
|
|
||||||
|`http.cors.allow-origin` |Which origins to allow. Defaults to `*`,
|
|`http.cors.allow-origin` |Which origins to allow. Defaults to `*`,
|
||||||
i.e. any origin.
|
i.e. any origin. If you prepend and append a `/` to the value, this will
|
||||||
|
be treated as a regular expression, allowing you to support HTTP and HTTPs.
|
||||||
|
for example using `/https?:\/\/localhost(:[0-9]+)?/` would return the
|
||||||
|
request header appropriately in both cases.
|
||||||
|
|
||||||
|`http.cors.max-age` |Browsers send a "preflight" OPTIONS-request to
|
|`http.cors.max-age` |Browsers send a "preflight" OPTIONS-request to
|
||||||
determine CORS settings. `max-age` defines how long the result should
|
determine CORS settings. `max-age` defines how long the result should
|
||||||
|
|
|
@ -19,9 +19,12 @@
|
||||||
|
|
||||||
package org.elasticsearch.http.netty;
|
package org.elasticsearch.http.netty;
|
||||||
|
|
||||||
|
import org.elasticsearch.rest.support.RestUtils;
|
||||||
import org.jboss.netty.channel.*;
|
import org.jboss.netty.channel.*;
|
||||||
import org.jboss.netty.handler.codec.http.HttpRequest;
|
import org.jboss.netty.handler.codec.http.HttpRequest;
|
||||||
|
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -30,9 +33,11 @@ import org.jboss.netty.handler.codec.http.HttpRequest;
|
||||||
public class HttpRequestHandler extends SimpleChannelUpstreamHandler {
|
public class HttpRequestHandler extends SimpleChannelUpstreamHandler {
|
||||||
|
|
||||||
private final NettyHttpServerTransport serverTransport;
|
private final NettyHttpServerTransport serverTransport;
|
||||||
|
private final Pattern corsPattern;
|
||||||
|
|
||||||
public HttpRequestHandler(NettyHttpServerTransport serverTransport) {
|
public HttpRequestHandler(NettyHttpServerTransport serverTransport) {
|
||||||
this.serverTransport = serverTransport;
|
this.serverTransport = serverTransport;
|
||||||
|
this.corsPattern = RestUtils.getCorsSettingRegex(serverTransport.settings());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -41,7 +46,7 @@ public class HttpRequestHandler extends SimpleChannelUpstreamHandler {
|
||||||
// the netty HTTP handling always copy over the buffer to its own buffer, either in NioWorker internally
|
// the netty HTTP handling always copy over the buffer to its own buffer, either in NioWorker internally
|
||||||
// when reading, or using a cumalation buffer
|
// when reading, or using a cumalation buffer
|
||||||
NettyHttpRequest httpRequest = new NettyHttpRequest(request, e.getChannel());
|
NettyHttpRequest httpRequest = new NettyHttpRequest(request, e.getChannel());
|
||||||
serverTransport.dispatchRequest(httpRequest, new NettyHttpChannel(serverTransport, e.getChannel(), httpRequest));
|
serverTransport.dispatchRequest(httpRequest, new NettyHttpChannel(serverTransport, e.getChannel(), httpRequest, corsPattern));
|
||||||
super.messageReceived(ctx, e);
|
super.messageReceived(ctx, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
package org.elasticsearch.http.netty;
|
package org.elasticsearch.http.netty;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
import org.apache.lucene.util.UnicodeUtil;
|
import org.apache.lucene.util.UnicodeUtil;
|
||||||
import org.elasticsearch.common.bytes.BytesReference;
|
import org.elasticsearch.common.bytes.BytesReference;
|
||||||
|
@ -40,6 +41,9 @@ import org.jboss.netty.handler.codec.http.*;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -57,12 +61,14 @@ public class NettyHttpChannel extends HttpChannel {
|
||||||
private final NettyHttpServerTransport transport;
|
private final NettyHttpServerTransport transport;
|
||||||
private final Channel channel;
|
private final Channel channel;
|
||||||
private final org.jboss.netty.handler.codec.http.HttpRequest nettyRequest;
|
private final org.jboss.netty.handler.codec.http.HttpRequest nettyRequest;
|
||||||
|
private Pattern corsPattern;
|
||||||
|
|
||||||
public NettyHttpChannel(NettyHttpServerTransport transport, Channel channel, NettyHttpRequest request) {
|
public NettyHttpChannel(NettyHttpServerTransport transport, Channel channel, NettyHttpRequest request, Pattern corsPattern) {
|
||||||
super(request);
|
super(request);
|
||||||
this.transport = transport;
|
this.transport = transport;
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
this.nettyRequest = request.request();
|
this.nettyRequest = request.request();
|
||||||
|
this.corsPattern = corsPattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -90,15 +96,21 @@ public class NettyHttpChannel extends HttpChannel {
|
||||||
} else {
|
} else {
|
||||||
resp = new DefaultHttpResponse(HttpVersion.HTTP_1_1, status);
|
resp = new DefaultHttpResponse(HttpVersion.HTTP_1_1, status);
|
||||||
}
|
}
|
||||||
if (RestUtils.isBrowser(nettyRequest.headers().get(HttpHeaders.Names.USER_AGENT))) {
|
if (RestUtils.isBrowser(nettyRequest.headers().get(USER_AGENT))) {
|
||||||
if (transport.settings().getAsBoolean("http.cors.enabled", true)) {
|
if (transport.settings().getAsBoolean("http.cors.enabled", true)) {
|
||||||
// Add support for cross-origin Ajax requests (CORS)
|
String originHeader = request.header(ORIGIN);
|
||||||
resp.headers().add("Access-Control-Allow-Origin", transport.settings().get("http.cors.allow-origin", "*"));
|
if (!Strings.isNullOrEmpty(originHeader)) {
|
||||||
|
if (corsPattern == null) {
|
||||||
|
resp.headers().add(ACCESS_CONTROL_ALLOW_ORIGIN, transport.settings().get("http.cors.allow-origin", "*"));
|
||||||
|
} else {
|
||||||
|
resp.headers().add(ACCESS_CONTROL_ALLOW_ORIGIN, corsPattern.matcher(originHeader).matches() ? originHeader : "null");
|
||||||
|
}
|
||||||
|
}
|
||||||
if (nettyRequest.getMethod() == HttpMethod.OPTIONS) {
|
if (nettyRequest.getMethod() == HttpMethod.OPTIONS) {
|
||||||
// Allow Ajax requests based on the CORS "preflight" request
|
// Allow Ajax requests based on the CORS "preflight" request
|
||||||
resp.headers().add("Access-Control-Max-Age", transport.settings().getAsInt("http.cors.max-age", 1728000));
|
resp.headers().add(ACCESS_CONTROL_MAX_AGE, transport.settings().getAsInt("http.cors.max-age", 1728000));
|
||||||
resp.headers().add("Access-Control-Allow-Methods", transport.settings().get("http.cors.allow-methods", "OPTIONS, HEAD, GET, POST, PUT, DELETE"));
|
resp.headers().add(ACCESS_CONTROL_ALLOW_METHODS, transport.settings().get("http.cors.allow-methods", "OPTIONS, HEAD, GET, POST, PUT, DELETE"));
|
||||||
resp.headers().add("Access-Control-Allow-Headers", transport.settings().get("http.cors.allow-headers", "X-Requested-With, Content-Type, Content-Length"));
|
resp.headers().add(ACCESS_CONTROL_ALLOW_HEADERS, transport.settings().get("http.cors.allow-headers", "X-Requested-With, Content-Type, Content-Length"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,9 +22,11 @@ package org.elasticsearch.rest.support;
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
import org.elasticsearch.common.Nullable;
|
import org.elasticsearch.common.Nullable;
|
||||||
import org.elasticsearch.common.path.PathTrie;
|
import org.elasticsearch.common.path.PathTrie;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -37,6 +39,7 @@ public class RestUtils {
|
||||||
return RestUtils.decodeComponent(value);
|
return RestUtils.decodeComponent(value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
public static final String HTTP_CORS_ALLOW_ORIGIN_SETTING = "http.cors.allow-origin";
|
||||||
|
|
||||||
public static boolean isBrowser(@Nullable String userAgent) {
|
public static boolean isBrowser(@Nullable String userAgent) {
|
||||||
if (userAgent == null) {
|
if (userAgent == null) {
|
||||||
|
@ -216,4 +219,19 @@ public class RestUtils {
|
||||||
return Character.MAX_VALUE;
|
return Character.MAX_VALUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if CORS setting is a regex
|
||||||
|
*/
|
||||||
|
public static Pattern getCorsSettingRegex(Settings settings) {
|
||||||
|
String corsSetting = settings.get(HTTP_CORS_ALLOW_ORIGIN_SETTING, "*");
|
||||||
|
int len = corsSetting.length();
|
||||||
|
boolean isRegex = len > 2 && corsSetting.startsWith("/") && corsSetting.endsWith("/");
|
||||||
|
|
||||||
|
if (isRegex) {
|
||||||
|
return Pattern.compile(corsSetting.substring(1, corsSetting.length()-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elasticsearch under one or more contributor
|
||||||
|
* license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright
|
||||||
|
* ownership. Elasticsearch licenses this file to you under
|
||||||
|
* the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.elasticsearch.rest;
|
||||||
|
|
||||||
|
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||||
|
import org.elasticsearch.test.rest.client.http.HttpResponse;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.elasticsearch.rest.CorsRegexTests.httpClient;
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class CorsRegexDefaultTests extends ElasticsearchIntegrationTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCorsSettingDefaultBehaviour() throws Exception {
|
||||||
|
String corsValue = "http://localhost:9200";
|
||||||
|
HttpResponse response = httpClient().method("GET").path("/").addHeader("User-Agent", "Mozilla Bar").addHeader("Origin", corsValue).execute();
|
||||||
|
|
||||||
|
assertThat(response.getStatusCode(), is(200));
|
||||||
|
assertThat(response.getHeaders(), hasKey("Access-Control-Allow-Origin"));
|
||||||
|
assertThat(response.getHeaders().get("Access-Control-Allow-Origin"), is("*"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testThatOmittingCorsHeaderDoesNotReturnAnything() throws Exception {
|
||||||
|
HttpResponse response = httpClient().method("GET").path("/").execute();
|
||||||
|
|
||||||
|
assertThat(response.getStatusCode(), is(200));
|
||||||
|
assertThat(response.getHeaders(), not(hasKey("Access-Control-Allow-Origin")));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elasticsearch under one or more contributor
|
||||||
|
* license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright
|
||||||
|
* ownership. Elasticsearch licenses this file to you under
|
||||||
|
* the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.elasticsearch.rest;
|
||||||
|
|
||||||
|
import org.apache.http.impl.client.HttpClients;
|
||||||
|
import org.elasticsearch.common.logging.ESLogger;
|
||||||
|
import org.elasticsearch.common.logging.Loggers;
|
||||||
|
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
import org.elasticsearch.common.transport.InetSocketTransportAddress;
|
||||||
|
import org.elasticsearch.http.HttpServerTransport;
|
||||||
|
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||||
|
import org.elasticsearch.test.rest.client.http.HttpRequestBuilder;
|
||||||
|
import org.elasticsearch.test.rest.client.http.HttpResponse;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
|
||||||
|
import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
|
||||||
|
import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope;
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@ClusterScope(scope = Scope.SUITE, numDataNodes = 1)
|
||||||
|
public class CorsRegexTests extends ElasticsearchIntegrationTest {
|
||||||
|
|
||||||
|
protected static final ESLogger logger = Loggers.getLogger(CorsRegexTests.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Settings nodeSettings(int nodeOrdinal) {
|
||||||
|
return ImmutableSettings.settingsBuilder()
|
||||||
|
.put("http.cors.allow-origin", "/https?:\\/\\/localhost(:[0-9]+)?/")
|
||||||
|
.put("network.host", "127.0.0.1")
|
||||||
|
.put(super.nodeSettings(nodeOrdinal))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testThatRegularExpressionWorksOnMatch() throws Exception {
|
||||||
|
String corsValue = "http://localhost:9200";
|
||||||
|
HttpResponse response = httpClient().method("GET").path("/").addHeader("User-Agent", "Mozilla Bar").addHeader("Origin", corsValue).execute();
|
||||||
|
assertResponseWithOriginheader(response, corsValue);
|
||||||
|
|
||||||
|
corsValue = "https://localhost:9200";
|
||||||
|
response = httpClient().method("GET").path("/").addHeader("User-Agent", "Mozilla Bar").addHeader("Origin", corsValue).execute();
|
||||||
|
assertResponseWithOriginheader(response, corsValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testThatRegularExpressionReturnsNullOnNonMatch() throws Exception {
|
||||||
|
HttpResponse response = httpClient().method("GET").path("/").addHeader("User-Agent", "Mozilla Bar").addHeader("Origin", "http://evil-host:9200").execute();
|
||||||
|
assertResponseWithOriginheader(response, "null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testThatSendingNoOriginHeaderReturnsNoAccessControlHeader() throws Exception {
|
||||||
|
HttpResponse response = httpClient().method("GET").path("/").addHeader("User-Agent", "Mozilla Bar").execute();
|
||||||
|
assertThat(response.getStatusCode(), is(200));
|
||||||
|
assertThat(response.getHeaders(), not(hasKey("Access-Control-Allow-Origin")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testThatRegularExpressionIsNotAppliedWithoutCorrectBrowserOnMatch() throws Exception {
|
||||||
|
HttpResponse response = httpClient().method("GET").path("/").execute();
|
||||||
|
assertThat(response.getStatusCode(), is(200));
|
||||||
|
assertThat(response.getHeaders(), not(hasKey("Access-Control-Allow-Origin")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testThatPreFlightRequestWorksOnMatch() throws Exception {
|
||||||
|
String corsValue = "http://localhost:9200";
|
||||||
|
HttpResponse response = httpClient().method("OPTIONS").path("/").addHeader("User-Agent", "Mozilla Bar").addHeader("Origin", corsValue).execute();
|
||||||
|
assertResponseWithOriginheader(response, corsValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testThatPreFlightRequestReturnsNullOnNonMatch() throws Exception {
|
||||||
|
HttpResponse response = httpClient().method("OPTIONS").path("/").addHeader("User-Agent", "Mozilla Bar").addHeader("Origin", "http://evil-host:9200").execute();
|
||||||
|
assertResponseWithOriginheader(response, "null");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HttpRequestBuilder httpClient() {
|
||||||
|
HttpServerTransport httpServerTransport = internalCluster().getDataNodeInstance(HttpServerTransport.class);
|
||||||
|
InetSocketAddress address = ((InetSocketTransportAddress) httpServerTransport.boundAddress().publishAddress()).address();
|
||||||
|
return new HttpRequestBuilder(HttpClients.createDefault()).host(address.getHostName()).port(address.getPort());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void assertResponseWithOriginheader(HttpResponse response, String expectedCorsHeader) {
|
||||||
|
assertThat(response.getStatusCode(), is(200));
|
||||||
|
assertThat(response.getHeaders(), hasKey("Access-Control-Allow-Origin"));
|
||||||
|
assertThat(response.getHeaders().get("Access-Control-Allow-Origin"), is(expectedCorsHeader));
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,15 +19,18 @@
|
||||||
|
|
||||||
package org.elasticsearch.rest.util;
|
package org.elasticsearch.rest.util;
|
||||||
|
|
||||||
|
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||||
import org.elasticsearch.rest.support.RestUtils;
|
import org.elasticsearch.rest.support.RestUtils;
|
||||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import static com.google.common.collect.Maps.newHashMap;
|
import static com.google.common.collect.Maps.newHashMap;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder;
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -122,4 +125,34 @@ public class RestUtilsTests extends ElasticsearchTestCase {
|
||||||
assertThat(params.get("p1"), equalTo("v1"));
|
assertThat(params.get("p1"), equalTo("v1"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCorsSettingIsARegex() {
|
||||||
|
assertCorsSettingRegex("/foo/", Pattern.compile("foo"));
|
||||||
|
assertCorsSettingRegex("/.*/", Pattern.compile(".*"));
|
||||||
|
assertCorsSettingRegex("/https?:\\/\\/localhost(:[0-9]+)?/", Pattern.compile("https?:\\/\\/localhost(:[0-9]+)?"));
|
||||||
|
assertCorsSettingRegexMatches("/https?:\\/\\/localhost(:[0-9]+)?/", true, "http://localhost:9200", "http://localhost:9215", "https://localhost:9200", "https://localhost");
|
||||||
|
assertCorsSettingRegexMatches("/https?:\\/\\/localhost(:[0-9]+)?/", false, "htt://localhost:9200", "http://localhost:9215/foo", "localhost:9215");
|
||||||
|
assertCorsSettingRegexIsNull("//");
|
||||||
|
assertCorsSettingRegexIsNull("/");
|
||||||
|
assertCorsSettingRegexIsNull("/foo");
|
||||||
|
assertCorsSettingRegexIsNull("foo");
|
||||||
|
assertCorsSettingRegexIsNull("");
|
||||||
|
assertThat(RestUtils.getCorsSettingRegex(ImmutableSettings.EMPTY), is(nullValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertCorsSettingRegexIsNull(String settingsValue) {
|
||||||
|
assertThat(RestUtils.getCorsSettingRegex(settingsBuilder().put("http.cors.allow-origin", settingsValue).build()), is(nullValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertCorsSettingRegex(String settingsValue, Pattern pattern) {
|
||||||
|
assertThat(RestUtils.getCorsSettingRegex(settingsBuilder().put("http.cors.allow-origin", settingsValue).build()).toString(), is(pattern.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertCorsSettingRegexMatches(String settingsValue, boolean expectMatch, String ... candidates) {
|
||||||
|
Pattern pattern = RestUtils.getCorsSettingRegex(settingsBuilder().put("http.cors.allow-origin", settingsValue).build());
|
||||||
|
for (String candidate : candidates) {
|
||||||
|
assertThat(String.format(Locale.ROOT, "Expected pattern %s to match against %s: %s", settingsValue, candidate, expectMatch),
|
||||||
|
pattern.matcher(candidate).matches(), is(expectMatch));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,16 +20,13 @@ package org.elasticsearch.test.rest.client.http;
|
||||||
|
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import org.apache.http.client.config.RequestConfig;
|
|
||||||
import org.apache.http.client.methods.*;
|
import org.apache.http.client.methods.*;
|
||||||
import org.apache.http.entity.StringEntity;
|
import org.apache.http.entity.StringEntity;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
import org.apache.lucene.util.IOUtils;
|
|
||||||
import org.elasticsearch.common.Strings;
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.logging.ESLogger;
|
import org.elasticsearch.common.logging.ESLogger;
|
||||||
import org.elasticsearch.common.logging.Loggers;
|
import org.elasticsearch.common.logging.Loggers;
|
||||||
import org.elasticsearch.common.transport.InetSocketTransportAddress;
|
import org.elasticsearch.common.transport.InetSocketTransportAddress;
|
||||||
import org.elasticsearch.common.transport.TransportAddress;
|
|
||||||
import org.elasticsearch.http.HttpServerTransport;
|
import org.elasticsearch.http.HttpServerTransport;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -147,6 +144,11 @@ public class HttpRequestBuilder {
|
||||||
return new HttpHead(buildUri());
|
return new HttpHead(buildUri());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (HttpOptions.METHOD_NAME.equalsIgnoreCase(method)) {
|
||||||
|
checkBodyNotSupported();
|
||||||
|
return new HttpOptions(buildUri());
|
||||||
|
}
|
||||||
|
|
||||||
if (HttpDeleteWithEntity.METHOD_NAME.equalsIgnoreCase(method)) {
|
if (HttpDeleteWithEntity.METHOD_NAME.equalsIgnoreCase(method)) {
|
||||||
return addOptionalBody(new HttpDeleteWithEntity(buildUri()));
|
return addOptionalBody(new HttpDeleteWithEntity(buildUri()));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue