Support trailing slashes on plugin _site URLs fix #2654

This commit is contained in:
David Pilato 2013-02-19 00:09:02 +01:00
parent cfaa859bb2
commit 8ab9d2dd1f
6 changed files with 239 additions and 3 deletions

View File

@ -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);

View File

@ -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";
}
}

View File

@ -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>"));
}
}

View File

@ -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();
}
}
}

View File

@ -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;
}
}

View File

@ -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>