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) {
|
||||
pluginName = path;
|
||||
sitePath = null;
|
||||
// TODO This is a path in the form of "/_plugin/head", without a trailing "/", which messes up
|
||||
// resources fetching if it does not exists, a better solution would be to send a redirect
|
||||
channel.sendResponse(new StringRestResponse(NOT_FOUND));
|
||||
// If a trailing / is missing, we redirect to the right page #2654
|
||||
channel.sendResponse(new HttpRedirectRestResponse(request.rawPath()+"/"));
|
||||
return;
|
||||
} else {
|
||||
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