Support trailing slashes on plugin _site URLs fix #2654
This commit is contained in:
parent
cfaa859bb2
commit
8ab9d2dd1f
|
@ -153,9 +153,8 @@ public class HttpServer extends AbstractLifecycleComponent<HttpServer> {
|
||||||
if (i1 == -1) {
|
if (i1 == -1) {
|
||||||
pluginName = path;
|
pluginName = path;
|
||||||
sitePath = null;
|
sitePath = null;
|
||||||
// TODO This is a path in the form of "/_plugin/head", without a trailing "/", which messes up
|
// If a trailing / is missing, we redirect to the right page #2654
|
||||||
// resources fetching if it does not exists, a better solution would be to send a redirect
|
channel.sendResponse(new HttpRedirectRestResponse(request.rawPath()+"/"));
|
||||||
channel.sendResponse(new StringRestResponse(NOT_FOUND));
|
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
pluginName = path.substring(0, i1);
|
pluginName = path.substring(0, i1);
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Licensed to ElasticSearch and Shay Banon 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redirect to another web page
|
||||||
|
*/
|
||||||
|
public class HttpRedirectRestResponse extends StringRestResponse {
|
||||||
|
|
||||||
|
public HttpRedirectRestResponse(String url) {
|
||||||
|
super(RestStatus.MOVED_PERMANENTLY, "<head><meta http-equiv=\"refresh\" content=\"0; URL="+url+"\"></head>");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String contentType() {
|
||||||
|
return "text/html";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elastic Search and Shay Banon 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.test.integration.plugin;
|
||||||
|
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
import org.elasticsearch.node.internal.InternalNode;
|
||||||
|
import org.elasticsearch.rest.RestStatus;
|
||||||
|
import org.elasticsearch.test.integration.AbstractNodesTests;
|
||||||
|
import org.elasticsearch.test.integration.rest.helper.HttpClient;
|
||||||
|
import org.elasticsearch.test.integration.rest.helper.HttpClientResponse;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We want to test site plugins
|
||||||
|
*/
|
||||||
|
public class SitePluginTests extends AbstractNodesTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRedirectSitePlugin() throws Exception {
|
||||||
|
|
||||||
|
Settings settings = settingsBuilder()
|
||||||
|
.put("path.plugins", "target/test-classes/org/elasticsearch/test/integration/plugin/")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
InternalNode node = (InternalNode) buildNode("test", settings);
|
||||||
|
node.start();
|
||||||
|
|
||||||
|
// We use an HTTP Client to test redirection
|
||||||
|
HttpClientResponse response = new HttpClient("http://localhost:9200").request("/_plugin/dummy");
|
||||||
|
assertThat(response.errorCode(), equalTo(RestStatus.MOVED_PERMANENTLY.getStatus()));
|
||||||
|
assertThat(response.response(), containsString("/_plugin/dummy/"));
|
||||||
|
|
||||||
|
// We test the real URL
|
||||||
|
response = new HttpClient("http://localhost:9200").request("/_plugin/dummy/");
|
||||||
|
assertThat(response.errorCode(), equalTo(RestStatus.OK.getStatus()));
|
||||||
|
assertThat(response.response(), containsString("<title>Dummy Site Plugin</title>"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elastic Search and Shay Banon 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.test.integration.rest.helper;
|
||||||
|
|
||||||
|
import org.elasticsearch.ElasticSearchException;
|
||||||
|
import org.elasticsearch.common.io.Streams;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
public class HttpClient {
|
||||||
|
|
||||||
|
private final URL baseUrl;
|
||||||
|
|
||||||
|
public HttpClient(String url) {
|
||||||
|
try {
|
||||||
|
baseUrl = new URL(url);
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
throw new ElasticSearchException("", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpClientResponse request(String path) {
|
||||||
|
return request("GET", path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpClientResponse request(String method, String path) {
|
||||||
|
URL url;
|
||||||
|
try {
|
||||||
|
url = new URL(baseUrl, path);
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
throw new ElasticSearchException("Cannot parse " + path, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpURLConnection urlConnection;
|
||||||
|
try {
|
||||||
|
urlConnection = (HttpURLConnection) url.openConnection();
|
||||||
|
urlConnection.setRequestMethod(method);
|
||||||
|
urlConnection.connect();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new ElasticSearchException("", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
int errorCode = -1;
|
||||||
|
try {
|
||||||
|
errorCode = urlConnection.getResponseCode();
|
||||||
|
InputStream inputStream = urlConnection.getInputStream();
|
||||||
|
String body = null;
|
||||||
|
try {
|
||||||
|
body = Streams.copyToString(new InputStreamReader(inputStream));
|
||||||
|
} catch (IOException e1) {
|
||||||
|
throw new ElasticSearchException("problem reading error stream", e1);
|
||||||
|
}
|
||||||
|
return new HttpClientResponse(body, errorCode, null);
|
||||||
|
} catch (IOException e) {
|
||||||
|
InputStream errStream = urlConnection.getErrorStream();
|
||||||
|
String body = null;
|
||||||
|
try {
|
||||||
|
body = Streams.copyToString(new InputStreamReader(errStream));
|
||||||
|
} catch (IOException e1) {
|
||||||
|
throw new ElasticSearchException("problem reading error stream", e1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new HttpClientResponse(body, errorCode, e);
|
||||||
|
} finally {
|
||||||
|
urlConnection.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elastic Search and Shay Banon 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.test.integration.rest.helper;
|
||||||
|
|
||||||
|
|
||||||
|
public class HttpClientResponse {
|
||||||
|
private final String response;
|
||||||
|
private final int errorCode;
|
||||||
|
private final Throwable e;
|
||||||
|
|
||||||
|
public HttpClientResponse(String response, int errorCode, Throwable e) {
|
||||||
|
this.response = response;
|
||||||
|
this.errorCode = errorCode;
|
||||||
|
this.e = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String response() {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int errorCode() {
|
||||||
|
return errorCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Throwable cause() {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Dummy Site Plugin</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>Welcome to this dummy elasticsearch plugin</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue