summaryrefslogtreecommitdiff
path: root/core/src/main/java/org/elasticsearch/http/HttpServer.java
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/main/java/org/elasticsearch/http/HttpServer.java')
-rw-r--r--core/src/main/java/org/elasticsearch/http/HttpServer.java185
1 files changed, 7 insertions, 178 deletions
diff --git a/core/src/main/java/org/elasticsearch/http/HttpServer.java b/core/src/main/java/org/elasticsearch/http/HttpServer.java
index 9971ce7722..5b1c0a32f8 100644
--- a/core/src/main/java/org/elasticsearch/http/HttpServer.java
+++ b/core/src/main/java/org/elasticsearch/http/HttpServer.java
@@ -21,39 +21,27 @@ package org.elasticsearch.http;
import org.elasticsearch.common.component.AbstractLifecycleComponent;
import org.elasticsearch.common.inject.Inject;
-import org.elasticsearch.common.io.FileSystemUtils;
import org.elasticsearch.common.io.Streams;
import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.env.Environment;
import org.elasticsearch.node.service.NodeService;
import org.elasticsearch.rest.BytesRestResponse;
-import org.elasticsearch.rest.RestChannel;
import org.elasticsearch.rest.RestController;
-import org.elasticsearch.rest.RestFilter;
-import org.elasticsearch.rest.RestFilterChain;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.RestStatus;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-import static java.util.Collections.unmodifiableMap;
import static org.elasticsearch.rest.RestStatus.FORBIDDEN;
import static org.elasticsearch.rest.RestStatus.INTERNAL_SERVER_ERROR;
-import static org.elasticsearch.rest.RestStatus.NOT_FOUND;
-import static org.elasticsearch.rest.RestStatus.OK;
/**
- *
+ * A component to serve http requests, backed by rest handlers.
*/
-public class HttpServer extends AbstractLifecycleComponent<HttpServer> {
+public class HttpServer extends AbstractLifecycleComponent<HttpServer> implements HttpServerAdapter {
private final Environment environment;
@@ -63,10 +51,6 @@ public class HttpServer extends AbstractLifecycleComponent<HttpServer> {
private final NodeService nodeService;
- private final boolean disableSites;
-
- private final PluginSiteFilter pluginSiteFilter = new PluginSiteFilter();
-
@Inject
public HttpServer(Settings settings, Environment environment, HttpServerTransport transport,
RestController restController,
@@ -77,25 +61,9 @@ public class HttpServer extends AbstractLifecycleComponent<HttpServer> {
this.restController = restController;
this.nodeService = nodeService;
nodeService.setHttpServer(this);
-
- this.disableSites = this.settings.getAsBoolean("http.disable_sites", false);
-
- transport.httpServerAdapter(new Dispatcher(this));
+ transport.httpServerAdapter(this);
}
- static class Dispatcher implements HttpServerAdapter {
-
- private final HttpServer server;
-
- Dispatcher(HttpServer server) {
- this.server = server;
- }
-
- @Override
- public void dispatchRequest(HttpRequest request, HttpChannel channel) {
- server.internalDispatchRequest(request, channel);
- }
- }
@Override
protected void doStart() {
@@ -125,26 +93,12 @@ public class HttpServer extends AbstractLifecycleComponent<HttpServer> {
return transport.stats();
}
- public void internalDispatchRequest(final HttpRequest request, final HttpChannel channel) {
- String rawPath = request.rawPath();
- if (rawPath.startsWith("/_plugin/")) {
- RestFilterChain filterChain = restController.filterChain(pluginSiteFilter);
- filterChain.continueProcessing(request, channel);
- return;
- } else if (rawPath.equals("/favicon.ico")) {
+ public void dispatchRequest(HttpRequest request, HttpChannel channel, ThreadContext threadContext) {
+ if (request.rawPath().equals("/favicon.ico")) {
handleFavicon(request, channel);
return;
}
- restController.dispatchRequest(request, channel);
- }
-
-
- class PluginSiteFilter extends RestFilter {
-
- @Override
- public void process(RestRequest request, RestChannel channel, RestFilterChain filterChain) throws IOException {
- handlePluginSite((HttpRequest) request, (HttpChannel) channel);
- }
+ restController.dispatchRequest(request, channel, threadContext);
}
void handleFavicon(HttpRequest request, HttpChannel channel) {
@@ -163,129 +117,4 @@ public class HttpServer extends AbstractLifecycleComponent<HttpServer> {
channel.sendResponse(new BytesRestResponse(FORBIDDEN));
}
}
-
- void handlePluginSite(HttpRequest request, HttpChannel channel) throws IOException {
- if (disableSites) {
- channel.sendResponse(new BytesRestResponse(FORBIDDEN));
- return;
- }
- if (request.method() == RestRequest.Method.OPTIONS) {
- // when we have OPTIONS request, simply send OK by default (with the Access Control Origin header which gets automatically added)
- channel.sendResponse(new BytesRestResponse(OK));
- return;
- }
- if (request.method() != RestRequest.Method.GET) {
- channel.sendResponse(new BytesRestResponse(FORBIDDEN));
- return;
- }
- // TODO for a "/_plugin" endpoint, we should have a page that lists all the plugins?
-
- String path = request.rawPath().substring("/_plugin/".length());
- int i1 = path.indexOf('/');
- String pluginName;
- String sitePath;
- if (i1 == -1) {
- pluginName = path;
- sitePath = null;
- // If a trailing / is missing, we redirect to the right page #2654
- String redirectUrl = request.rawPath() + "/";
- BytesRestResponse restResponse = new BytesRestResponse(RestStatus.MOVED_PERMANENTLY, "text/html", "<head><meta http-equiv=\"refresh\" content=\"0; URL=" + redirectUrl + "\"></head>");
- restResponse.addHeader("Location", redirectUrl);
- channel.sendResponse(restResponse);
- return;
- } else {
- pluginName = path.substring(0, i1);
- sitePath = path.substring(i1 + 1);
- }
-
- // we default to index.html, or what the plugin provides (as a unix-style path)
- // this is a relative path under _site configured by the plugin.
- if (sitePath.length() == 0) {
- sitePath = "index.html";
- } else {
- // remove extraneous leading slashes, its not an absolute path.
- while (sitePath.length() > 0 && sitePath.charAt(0) == '/') {
- sitePath = sitePath.substring(1);
- }
- }
- final Path siteFile = environment.pluginsFile().resolve(pluginName).resolve("_site");
-
- final String separator = siteFile.getFileSystem().getSeparator();
- // Convert file separators.
- sitePath = sitePath.replace("/", separator);
-
- Path file = siteFile.resolve(sitePath);
-
- // return not found instead of forbidden to prevent malicious requests to find out if files exist or dont exist
- if (!Files.exists(file) || FileSystemUtils.isHidden(file) || !file.toAbsolutePath().normalize().startsWith(siteFile.toAbsolutePath().normalize())) {
- channel.sendResponse(new BytesRestResponse(NOT_FOUND));
- return;
- }
-
- BasicFileAttributes attributes = Files.readAttributes(file, BasicFileAttributes.class);
- if (!attributes.isRegularFile()) {
- // If it's not a dir, we send a 403
- if (!attributes.isDirectory()) {
- channel.sendResponse(new BytesRestResponse(FORBIDDEN));
- return;
- }
- // We don't serve dir but if index.html exists in dir we should serve it
- file = file.resolve("index.html");
- if (!Files.exists(file) || FileSystemUtils.isHidden(file) || !Files.isRegularFile(file)) {
- channel.sendResponse(new BytesRestResponse(FORBIDDEN));
- return;
- }
- }
-
- try {
- byte[] data = Files.readAllBytes(file);
- channel.sendResponse(new BytesRestResponse(OK, guessMimeType(sitePath), data));
- } catch (IOException e) {
- channel.sendResponse(new BytesRestResponse(INTERNAL_SERVER_ERROR));
- }
- }
-
-
- // TODO: Don't respond with a mime type that violates the request's Accept header
- private String guessMimeType(String path) {
- int lastDot = path.lastIndexOf('.');
- if (lastDot == -1) {
- return "";
- }
- String extension = path.substring(lastDot + 1).toLowerCase(Locale.ROOT);
- String mimeType = DEFAULT_MIME_TYPES.get(extension);
- if (mimeType == null) {
- return "";
- }
- return mimeType;
- }
-
- static {
- // This is not an exhaustive list, just the most common types. Call registerMimeType() to add more.
- Map<String, String> mimeTypes = new HashMap<>();
- mimeTypes.put("txt", "text/plain");
- mimeTypes.put("css", "text/css");
- mimeTypes.put("csv", "text/csv");
- mimeTypes.put("htm", "text/html");
- mimeTypes.put("html", "text/html");
- mimeTypes.put("xml", "text/xml");
- mimeTypes.put("js", "text/javascript"); // Technically it should be application/javascript (RFC 4329), but IE8 struggles with that
- mimeTypes.put("xhtml", "application/xhtml+xml");
- mimeTypes.put("json", "application/json");
- mimeTypes.put("pdf", "application/pdf");
- mimeTypes.put("zip", "application/zip");
- mimeTypes.put("tar", "application/x-tar");
- mimeTypes.put("gif", "image/gif");
- mimeTypes.put("jpeg", "image/jpeg");
- mimeTypes.put("jpg", "image/jpeg");
- mimeTypes.put("tiff", "image/tiff");
- mimeTypes.put("tif", "image/tiff");
- mimeTypes.put("png", "image/png");
- mimeTypes.put("svg", "image/svg+xml");
- mimeTypes.put("ico", "image/vnd.microsoft.icon");
- mimeTypes.put("mp3", "audio/mpeg");
- DEFAULT_MIME_TYPES = unmodifiableMap(mimeTypes);
- }
-
- public static final Map<String, String> DEFAULT_MIME_TYPES;
}