Skip to content

Commit

Permalink
Plugins: Remove site plugins
Browse files Browse the repository at this point in the history
Site plugins used to be used for things like kibana and marvel, but
there is no longer a need since kibana (and marvel as a kibana plugin)
uses node.js. This change removes site plugins, as well as the flag for
jvm plugins. Now all plugins are jvm plugins.
  • Loading branch information
rjernst committed Jan 17, 2016
1 parent b4538a5 commit 3b78267
Show file tree
Hide file tree
Showing 42 changed files with 77 additions and 1,031 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,6 @@ public class PluginBuildPlugin extends BuildPlugin {
include 'config/**'
include 'bin/**'
}
from('src/site') {
include '_site/**'
}
}
project.assemble.dependsOn(bundle)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,9 @@ class PluginPropertiesExtension {
@Input
String description

@Input
boolean jvm = true

@Input
String classname

@Input
boolean site = false

@Input
boolean isolated = true

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ class PluginPropertiesTask extends Copy {
if (extension.description == null) {
throw new InvalidUserDataException('description is a required setting for esplugin')
}
if (extension.jvm && extension.classname == null) {
throw new InvalidUserDataException('classname is a required setting for esplugin with jvm=true')
if (extension.classname == null) {
throw new InvalidUserDataException('classname is a required setting for esplugin')
}
doFirst {
if (extension.jvm && extension.isolated == false) {
if (extension.isolated == false) {
String warning = "WARNING: Disabling plugin isolation in ${project.path} is deprecated and will be removed in the future"
logger.warn("${'=' * warning.length()}\n${warning}\n${'=' * warning.length()}")
}
Expand All @@ -74,10 +74,8 @@ class PluginPropertiesTask extends Copy {
'version': extension.version,
'elasticsearchVersion': VersionProperties.elasticsearch,
'javaVersion': project.targetCompatibility as String,
'jvm': extension.jvm as String,
'site': extension.site as String,
'isolated': extension.isolated as String,
'classname': extension.jvm ? extension.classname : 'NA'
'classname': extension.classname
]
}
}
30 changes: 1 addition & 29 deletions buildSrc/src/main/resources/plugin-descriptor.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,13 @@
# This file must exist as 'plugin-descriptor.properties' at
# the root directory of all plugins.
#
# A plugin can be 'site', 'jvm', or both.
#
### example site plugin for "foo":
#
# foo.zip <-- zip file for the plugin, with this structure:
# _site/ <-- the contents that will be served
# plugin-descriptor.properties <-- example contents below:
#
# site=true
# description=My cool plugin
# version=1.0
#
### example jvm plugin for "foo"
### example plugin for "foo"
#
# foo.zip <-- zip file for the plugin, with this structure:
# <arbitrary name1>.jar <-- classes, resources, dependencies
# <arbitrary nameN>.jar <-- any number of jars
# plugin-descriptor.properties <-- example contents below:
#
# jvm=true
# classname=foo.bar.BazPlugin
# description=My cool plugin
# version=2.0
Expand All @@ -38,21 +25,6 @@ version=${version}
#
# 'name': the plugin name
name=${name}

### mandatory elements for site plugins:
#
# 'site': set to true to indicate contents of the _site/
# directory in the root of the plugin should be served.
site=${site}
#
### mandatory elements for jvm plugins :
#
# 'jvm': true if the 'classname' class should be loaded
# from jar files in the root directory of the plugin.
# Note that only jar files in the root directory are
# added to the classpath for the plugin! If you need
# other resources, package them into a resources jar.
jvm=${jvm}
#
# 'classname': the name of the class to load, fully-qualified.
classname=${classname}
Expand Down
150 changes: 2 additions & 148 deletions core/src/main/java/org/elasticsearch/http/HttpServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
import static org.elasticsearch.rest.RestStatus.OK;

/**
*
* A component to serve http requests, backed by rest handlers.
*/
public class HttpServer extends AbstractLifecycleComponent<HttpServer> {

Expand All @@ -63,10 +63,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,
Expand All @@ -77,9 +73,6 @@ public HttpServer(Settings settings, Environment environment, HttpServerTranspor
this.restController = restController;
this.nodeService = nodeService;
nodeService.setHttpServer(this);

this.disableSites = this.settings.getAsBoolean("http.disable_sites", false);

transport.httpServerAdapter(new Dispatcher(this));
}

Expand Down Expand Up @@ -126,27 +119,13 @@ public HttpStats 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")) {
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);
}
}

void handleFavicon(HttpRequest request, HttpChannel channel) {
if (request.method() == RestRequest.Method.GET) {
try {
Expand All @@ -163,129 +142,4 @@ void handleFavicon(HttpRequest request, HttpChannel channel) {
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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@

public class DummyPluginInfo extends PluginInfo {

private DummyPluginInfo(String name, String description, boolean site, String version, boolean jvm, String classname, boolean isolated) {
super(name, description, site, version, jvm, classname, isolated);
private DummyPluginInfo(String name, String description, String version, String classname, boolean isolated) {
super(name, description, version, classname, isolated);
}

public static final DummyPluginInfo INSTANCE = new DummyPluginInfo("dummy_plugin_name", "dummy plugin description", true, "dummy_plugin_version", true, "DummyPluginName", true);
public static final DummyPluginInfo INSTANCE = new DummyPluginInfo("dummy_plugin_name", "dummy plugin description", "dummy_plugin_version", "DummyPluginName", true);
}
Loading

0 comments on commit 3b78267

Please sign in to comment.