mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 05:07:41 +00:00
GUACAMOLE-1298: Merge automatically limit HTTP request size.
This commit is contained in:
@@ -254,6 +254,11 @@
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.7.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jul-to-slf4j</artifactId>
|
||||
<version>1.7.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
@@ -435,33 +440,38 @@
|
||||
<dependency>
|
||||
<groupId>com.google.inject</groupId>
|
||||
<artifactId>guice</artifactId>
|
||||
<version>3.0</version>
|
||||
<version>4.2.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.inject.extensions</groupId>
|
||||
<artifactId>guice-assistedinject</artifactId>
|
||||
<version>3.0</version>
|
||||
<version>4.2.3</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Guice Servlet -->
|
||||
<dependency>
|
||||
<groupId>com.google.inject.extensions</groupId>
|
||||
<artifactId>guice-servlet</artifactId>
|
||||
<version>3.0</version>
|
||||
<version>4.2.3</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Jersey - JAX-RS Implementation -->
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey</groupId>
|
||||
<artifactId>jersey-server</artifactId>
|
||||
<version>1.17.1</version>
|
||||
<groupId>org.glassfish.jersey.containers</groupId>
|
||||
<artifactId>jersey-container-servlet-core</artifactId>
|
||||
<version>2.31</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.inject</groupId>
|
||||
<artifactId>jersey-hk2</artifactId>
|
||||
<version>2.31</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Jersey - Guice extension -->
|
||||
<!-- Guice bridge for HK2 - the dependency injection framework integrated with Jersey 2.x -->
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey.contribs</groupId>
|
||||
<artifactId>jersey-guice</artifactId>
|
||||
<version>1.17.1</version>
|
||||
<groupId>org.glassfish.hk2</groupId>
|
||||
<artifactId>guice-bridge</artifactId>
|
||||
<version>2.6.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JSR-250 annotations -->
|
||||
@@ -473,9 +483,9 @@
|
||||
|
||||
<!-- Jackson for JSON support -->
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey</groupId>
|
||||
<artifactId>jersey-json</artifactId>
|
||||
<version>1.17.1</version>
|
||||
<groupId>org.glassfish.jersey.media</groupId>
|
||||
<artifactId>jersey-media-json-jackson</artifactId>
|
||||
<version>2.31</version>
|
||||
|
||||
<!-- Exclude StAX API, which is part of Java 6 -->
|
||||
<exclusions>
|
||||
|
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF 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.apache.guacamole;
|
||||
|
||||
import com.google.inject.Injector;
|
||||
import javax.inject.Inject;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.ws.rs.ApplicationPath;
|
||||
import org.glassfish.hk2.api.ServiceLocator;
|
||||
import org.glassfish.jersey.jackson.JacksonFeature;
|
||||
import org.glassfish.jersey.server.ResourceConfig;
|
||||
import org.jvnet.hk2.guice.bridge.api.GuiceBridge;
|
||||
import org.jvnet.hk2.guice.bridge.api.GuiceIntoHK2Bridge;
|
||||
import org.slf4j.bridge.SLF4JBridgeHandler;
|
||||
|
||||
/**
|
||||
* JAX-RS Application which serves as the root definition of the Guacamole
|
||||
* REST API. The HK2 dependency injection used by Jersey is automatically
|
||||
* bridged to Guice, allowing injections managed by Guice to be injected within
|
||||
* classes served by Jersey.
|
||||
*/
|
||||
@ApplicationPath("/*")
|
||||
public class GuacamoleApplication extends ResourceConfig {
|
||||
|
||||
/**
|
||||
* Creates a new GuacamoleApplication which defines the Guacamole REST API,
|
||||
* automatically configuring Jersey's HK2 dependency injection to
|
||||
* additionally pull services from a Guice injector.
|
||||
*
|
||||
* @param servletContext
|
||||
* The ServletContext which has already associated with a Guice
|
||||
* injector via a GuacamoleServletContextListener.
|
||||
*
|
||||
* @param serviceLocator
|
||||
* The HK2 service locator (injector).
|
||||
*/
|
||||
@Inject
|
||||
public GuacamoleApplication(ServletContext servletContext,
|
||||
ServiceLocator serviceLocator) {
|
||||
|
||||
// Bridge Jersey logging (java.util.logging) to SLF4J
|
||||
SLF4JBridgeHandler.removeHandlersForRootLogger();
|
||||
SLF4JBridgeHandler.install();
|
||||
|
||||
// Bridge HK2 service locator with Guice injector
|
||||
Injector guiceInjector = (Injector) servletContext.getAttribute(GuacamoleServletContextListener.GUICE_INJECTOR);
|
||||
GuiceBridge.getGuiceBridge().initializeGuiceBridge(serviceLocator);
|
||||
GuiceIntoHK2Bridge bridge = serviceLocator.getService(GuiceIntoHK2Bridge.class);
|
||||
bridge.bridgeGuiceInjector(guiceInjector);
|
||||
|
||||
// Automatically scan for REST resources
|
||||
packages("org.apache.guacamole.rest");
|
||||
|
||||
// Use Jackson for JSON
|
||||
register(JacksonFeature.class);
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -21,11 +21,12 @@ package org.apache.guacamole;
|
||||
|
||||
import org.apache.guacamole.tunnel.TunnelModule;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Stage;
|
||||
import com.google.inject.servlet.GuiceServletContextListener;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import javax.inject.Inject;
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import org.apache.guacamole.environment.Environment;
|
||||
import org.apache.guacamole.environment.LocalEnvironment;
|
||||
@@ -41,9 +42,45 @@ import org.slf4j.LoggerFactory;
|
||||
/**
|
||||
* A ServletContextListener to listen for initialization of the servlet context
|
||||
* in order to set up dependency injection.
|
||||
*
|
||||
* NOTE: Guacamole's REST API uses Jersey 2.x which does not natively support
|
||||
* dependency injection using Guice. It DOES support dependency injection using
|
||||
* HK2, which supports bi-directional bridging with Guice.
|
||||
*
|
||||
* The overall process is thus:
|
||||
*
|
||||
* 1. Application initialization proceeds using GuacamoleServletContextListener,
|
||||
* a subclass of GuiceServletContextListener, with all HTTP requests being
|
||||
* routed through GuiceFilter which serves as the absolute root.
|
||||
*
|
||||
* 2. GuacamoleServletContextListener prepares the Guice injector, storing the
|
||||
* injector within the ServletContext such that it can later be bridged with
|
||||
* HK2.
|
||||
*
|
||||
* 3. Several of the modules used to prepare the Guice injector are
|
||||
* ServletModule subclasses, which define HTTP request paths that GuiceFilter
|
||||
* should route to specific servlets. One of these paths is "/api/*" (the
|
||||
* root of the REST API) which is routed to Jersey's ServletContainer servlet
|
||||
* (the root of Jersey's JAX-RS implementation).
|
||||
*
|
||||
* 4. Configuration information passed to Jersey's ServletContainer tells Jersey
|
||||
* to use the GuacamoleApplication class (a subclass of ResourceConfig) to
|
||||
* define the rest of the resources and any other configuration.
|
||||
*
|
||||
* 5. When Jersey creates its instance of GuacamoleApplication, the
|
||||
* initialization process of GuacamoleApplication pulls the Guice injector
|
||||
* from the ServletContext, completes the HK2 bridging, and configures Jersey
|
||||
* to automatically locate and inject all REST services.
|
||||
*/
|
||||
public class GuacamoleServletContextListener extends GuiceServletContextListener {
|
||||
|
||||
/**
|
||||
* The name of the ServletContext attribute which will contain a reference
|
||||
* to the Guice injector once the contextInitialized() event has been
|
||||
* handled.
|
||||
*/
|
||||
public static final String GUICE_INJECTOR = "GUAC_GUICE_INJECTOR";
|
||||
|
||||
/**
|
||||
* Logger for this class.
|
||||
*/
|
||||
@@ -65,6 +102,12 @@ public class GuacamoleServletContextListener extends GuiceServletContextListener
|
||||
@Inject
|
||||
private List<AuthenticationProvider> authProviders;
|
||||
|
||||
/**
|
||||
* Internal reference to the Guice injector that was lazily created when
|
||||
* getInjector() was first invoked.
|
||||
*/
|
||||
private final AtomicReference<Injector> guiceInjector = new AtomicReference<>();
|
||||
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent servletContextEvent) {
|
||||
|
||||
@@ -78,14 +121,29 @@ public class GuacamoleServletContextListener extends GuiceServletContextListener
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
// NOTE: The superclass implementation of contextInitialized() is
|
||||
// expected to invoke getInjector(), hence the need to call AFTER
|
||||
// setting up the environment and session map
|
||||
super.contextInitialized(servletContextEvent);
|
||||
|
||||
// Inject any annotated members of this class
|
||||
Injector injector = getInjector();
|
||||
injector.injectMembers(this);
|
||||
|
||||
// Store reference to injector for use by Jersey and HK2 bridge
|
||||
servletContextEvent.getServletContext().setAttribute(GUICE_INJECTOR, injector);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Injector getInjector() {
|
||||
return guiceInjector.updateAndGet((current) -> {
|
||||
|
||||
// Create injector
|
||||
// Use existing injector if already created
|
||||
if (current != null)
|
||||
return current;
|
||||
|
||||
// Create new injector if necessary
|
||||
Injector injector = Guice.createInjector(Stage.PRODUCTION,
|
||||
new EnvironmentModule(environment),
|
||||
new LogModule(environment),
|
||||
@@ -94,17 +152,16 @@ public class GuacamoleServletContextListener extends GuiceServletContextListener
|
||||
new TunnelModule()
|
||||
);
|
||||
|
||||
// Inject any annotated members of this class
|
||||
injector.injectMembers(this);
|
||||
|
||||
return injector;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent servletContextEvent) {
|
||||
|
||||
super.contextDestroyed(servletContextEvent);
|
||||
// Clean up reference to Guice injector
|
||||
servletContextEvent.getServletContext().removeAttribute(GUICE_INJECTOR);
|
||||
|
||||
// Shutdown TokenSessionMap
|
||||
if (sessionMap != null)
|
||||
@@ -116,6 +173,9 @@ public class GuacamoleServletContextListener extends GuiceServletContextListener
|
||||
authProvider.shutdown();
|
||||
}
|
||||
|
||||
// Continue any Guice-specific cleanup
|
||||
super.contextDestroyed(servletContextEvent);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -33,18 +33,15 @@ import org.apache.guacamole.GuacamoleException;
|
||||
public class APIException extends WebApplicationException {
|
||||
|
||||
/**
|
||||
* Construct a new APIException based on the given GuacamoleException and
|
||||
* HTTP status. The details of the GuacamoleException relevant to the REST
|
||||
* API will be exposed via an APIError.
|
||||
*
|
||||
* @param status
|
||||
* The HTTP status which corresponds to the GuacamoleException.
|
||||
* Construct a new APIException based on the given GuacamoleException. The
|
||||
* details of the GuacamoleException relevant to the REST API will be
|
||||
* exposed via an APIError.
|
||||
*
|
||||
* @param exception
|
||||
* The GuacamoleException that occurred.
|
||||
*/
|
||||
public APIException(Response.Status status, GuacamoleException exception) {
|
||||
super(Response.status(status)
|
||||
public APIException(GuacamoleException exception) {
|
||||
super(Response.status(exception.getHttpStatusCode())
|
||||
.type(MediaType.APPLICATION_JSON)
|
||||
.entity(new APIError(exception))
|
||||
.build());
|
||||
|
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF 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.apache.guacamole.rest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import org.apache.guacamole.GuacamoleClientOverrunException;
|
||||
|
||||
/**
|
||||
* InputStream implementation which limits the body of REST API requests to
|
||||
* a particular maximum size. If an attempt is made to read from a REST API
|
||||
* request which exceeds this limit, the read attempt will be aborted by
|
||||
* throwing an APIException.
|
||||
*/
|
||||
public class LimitedRequestInputStream extends InputStream {
|
||||
|
||||
/**
|
||||
* The InputStream being limited.
|
||||
*/
|
||||
private final InputStream stream;
|
||||
|
||||
/**
|
||||
* The maximum number of bytes to allow to be read or skipped.
|
||||
*/
|
||||
private final long maxLength;
|
||||
|
||||
/**
|
||||
* The total number of bytes that have been read or skipped from the stream
|
||||
* thus far.
|
||||
*/
|
||||
private long bytesRead = 0;
|
||||
|
||||
/**
|
||||
* Wraps the given InputStream, ensuring that the overall number of bytes
|
||||
* read or skipped does not exceed the given maximum length.
|
||||
*
|
||||
* @param stream
|
||||
* The InputStream to limit.
|
||||
*
|
||||
* @param maxLength
|
||||
* The maximum number of bytes to allow to be read or skipped.
|
||||
*/
|
||||
public LimitedRequestInputStream(InputStream stream, long maxLength) {
|
||||
this.stream = stream;
|
||||
this.maxLength = maxLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Immediately verifies that the stream length limit has not been exceeded.
|
||||
* If the length limit has been exceeded, an APIException is thrown
|
||||
* indicating that the request body is too large.
|
||||
*
|
||||
* @throws APIException
|
||||
* If the length limit has been exceeded.
|
||||
*/
|
||||
private synchronized void recheckLength() throws APIException {
|
||||
if (bytesRead > maxLength)
|
||||
throw new APIException(new GuacamoleClientOverrunException("Request body/entity too large."));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the current number of bytes read based on the return value of a
|
||||
* read-like operation such as read() or skip(). If the maximum stream
|
||||
* length is exceeded as a result of the read, an APIException indicating
|
||||
* this is thrown.
|
||||
*
|
||||
* NOTE: To avoid unnecessary read operations, recheckLength() should be
|
||||
* manually called before performing any read operation. This function will
|
||||
* perform the same checks, but can inherently only do so AFTER the read
|
||||
* operation has occurred.
|
||||
*
|
||||
* @param change
|
||||
* The number of bytes that have been read or skipped, or -1 if the
|
||||
* read-like operation has failed (and no bytes have been read).
|
||||
*
|
||||
* @return
|
||||
* The provided number of bytes read/skipped.
|
||||
*
|
||||
* @throws APIException
|
||||
* If the read-like operation that occurred has caused the stream
|
||||
* length to exceed its maximum.
|
||||
*/
|
||||
private synchronized long limitedRead(long change) throws APIException {
|
||||
|
||||
if (change != -1) {
|
||||
bytesRead += change;
|
||||
recheckLength();
|
||||
}
|
||||
|
||||
return change;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
stream.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
return stream.available();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long skip(long l) throws IOException {
|
||||
recheckLength();
|
||||
return limitedRead(stream.skip(l));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] bytes, int i, int i1) throws IOException {
|
||||
recheckLength();
|
||||
return (int) limitedRead(stream.read(bytes, i, i1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] bytes) throws IOException {
|
||||
recheckLength();
|
||||
return (int) limitedRead(stream.read(bytes));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
|
||||
recheckLength();
|
||||
|
||||
int value = stream.read();
|
||||
if (value != -1)
|
||||
limitedRead(1);
|
||||
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF 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.apache.guacamole.rest;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import javax.ws.rs.HttpMethod;
|
||||
|
||||
/**
|
||||
* An annotation for using the HTTP PATCH method in the REST endpoints.
|
||||
*/
|
||||
@Target({ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@HttpMethod("PATCH")
|
||||
public @interface PATCH {}
|
@@ -19,9 +19,10 @@
|
||||
|
||||
package org.apache.guacamole.rest;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
@@ -83,6 +84,10 @@ public class RESTExceptionMapper implements ExceptionMapper<Throwable> {
|
||||
@Override
|
||||
public Response toResponse(Throwable t) {
|
||||
|
||||
// Pass WebApplicationException responses through untouched
|
||||
if (t instanceof WebApplicationException)
|
||||
return ((WebApplicationException) t).getResponse();
|
||||
|
||||
// Ensure any associated session is invalidated if unauthorized
|
||||
if (t instanceof GuacamoleUnauthorizedException) {
|
||||
String token = getAuthenticationToken();
|
||||
|
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF 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.apache.guacamole.rest;
|
||||
|
||||
import com.google.inject.matcher.AbstractMatcher;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import javax.ws.rs.HttpMethod;
|
||||
import javax.ws.rs.Path;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
|
||||
/**
|
||||
* A Guice Matcher which matches only methods which throw GuacamoleException
|
||||
* (or a subclass thereof) and are explicitly annotated as with an HTTP method
|
||||
* annotation like <code>@GET</code> or <code>@POST</code>. Any method which
|
||||
* throws GuacamoleException and is annotated with an annotation that is
|
||||
* annotated with <code>@HttpMethod</code> will match.
|
||||
*/
|
||||
public class RESTMethodMatcher extends AbstractMatcher<Method> {
|
||||
|
||||
/**
|
||||
* Returns whether the given method throws the specified exception type,
|
||||
* including any subclasses of that type.
|
||||
*
|
||||
* @param method
|
||||
* The method to test.
|
||||
*
|
||||
* @param exceptionType
|
||||
* The exception type to test for.
|
||||
*
|
||||
* @return
|
||||
* true if the given method throws an exception of the specified type,
|
||||
* false otherwise.
|
||||
*/
|
||||
private boolean methodThrowsException(Method method,
|
||||
Class<? extends Exception> exceptionType) {
|
||||
|
||||
// Check whether the method throws an exception of the specified type
|
||||
for (Class<?> thrownType : method.getExceptionTypes()) {
|
||||
if (exceptionType.isAssignableFrom(thrownType))
|
||||
return true;
|
||||
}
|
||||
|
||||
// No such exception is declared to be thrown
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given method is annotated as a REST method. A REST
|
||||
* method is annotated with an annotation which is annotated with
|
||||
* <code>@HttpMethod</code> or <code>@Path</code>.
|
||||
*
|
||||
* @param method
|
||||
* The method to test.
|
||||
*
|
||||
* @return
|
||||
* true if the given method is annotated as a REST method, false
|
||||
* otherwise.
|
||||
*/
|
||||
private boolean isRESTMethod(Method method) {
|
||||
|
||||
// Check whether the required REST annotations are present
|
||||
for (Annotation annotation : method.getAnnotations()) {
|
||||
|
||||
// A method is a REST method if it is annotated with @HttpMethod
|
||||
Class<? extends Annotation> annotationType = annotation.annotationType();
|
||||
if (annotationType.isAnnotationPresent(HttpMethod.class))
|
||||
return true;
|
||||
|
||||
// A method is a REST method if it is annotated with @Path
|
||||
if (Path.class.isAssignableFrom(annotationType))
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
// A method is also REST method if it overrides a REST method within
|
||||
// the superclass
|
||||
Class<?> superclass = method.getDeclaringClass().getSuperclass();
|
||||
if (superclass != null) {
|
||||
|
||||
// Recheck against identical method within superclass
|
||||
try {
|
||||
return isRESTMethod(superclass.getMethod(method.getName(),
|
||||
method.getParameterTypes()));
|
||||
}
|
||||
|
||||
// If there is no such method, then this method cannot possibly be
|
||||
// a REST method
|
||||
catch (NoSuchMethodException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Lacking a superclass, the search stops here - it's not a REST method
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method) {
|
||||
|
||||
// Guacamole REST methods are REST methods which throw
|
||||
// GuacamoleExceptions
|
||||
return isRESTMethod(method)
|
||||
&& methodThrowsException(method, GuacamoleException.class);
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -19,18 +19,14 @@
|
||||
|
||||
package org.apache.guacamole.rest;
|
||||
|
||||
import org.apache.guacamole.rest.event.ListenerService;
|
||||
import org.apache.guacamole.rest.session.UserContextResourceFactory;
|
||||
import org.apache.guacamole.rest.session.SessionRESTService;
|
||||
import com.google.inject.Scopes;
|
||||
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||
import com.google.inject.matcher.Matchers;
|
||||
import com.google.inject.servlet.ServletModule;
|
||||
import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import java.util.Collections;
|
||||
import org.apache.guacamole.rest.event.ListenerService;
|
||||
import org.apache.guacamole.rest.session.UserContextResourceFactory;
|
||||
import org.apache.guacamole.GuacamoleApplication;
|
||||
import org.apache.guacamole.rest.activeconnection.ActiveConnectionModule;
|
||||
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
|
||||
import org.apache.guacamole.rest.auth.TokenRESTService;
|
||||
import org.apache.guacamole.rest.auth.AuthTokenGenerator;
|
||||
import org.apache.guacamole.rest.auth.AuthenticationService;
|
||||
import org.apache.guacamole.rest.auth.DecorationService;
|
||||
@@ -38,15 +34,14 @@ import org.apache.guacamole.rest.auth.SecureRandomAuthTokenGenerator;
|
||||
import org.apache.guacamole.rest.auth.TokenSessionMap;
|
||||
import org.apache.guacamole.rest.connection.ConnectionModule;
|
||||
import org.apache.guacamole.rest.connectiongroup.ConnectionGroupModule;
|
||||
import org.apache.guacamole.rest.extension.ExtensionRESTService;
|
||||
import org.apache.guacamole.rest.language.LanguageRESTService;
|
||||
import org.apache.guacamole.rest.patch.PatchRESTService;
|
||||
import org.apache.guacamole.rest.session.SessionResourceFactory;
|
||||
import org.apache.guacamole.rest.sharingprofile.SharingProfileModule;
|
||||
import org.apache.guacamole.rest.tunnel.TunnelCollectionResourceFactory;
|
||||
import org.apache.guacamole.rest.tunnel.TunnelResourceFactory;
|
||||
import org.apache.guacamole.rest.user.UserModule;
|
||||
import org.apache.guacamole.rest.usergroup.UserGroupModule;
|
||||
import org.glassfish.jersey.servlet.ServletContainer;
|
||||
import org.glassfish.jersey.servlet.ServletProperties;
|
||||
import org.webjars.servlet.WebjarsServlet;
|
||||
|
||||
/**
|
||||
@@ -84,17 +79,7 @@ public class RESTServiceModule extends ServletModule {
|
||||
bind(AuthTokenGenerator.class).to(SecureRandomAuthTokenGenerator.class);
|
||||
bind(DecorationService.class);
|
||||
|
||||
// Automatically translate GuacamoleExceptions for REST methods
|
||||
bind(RESTExceptionMapper.class);
|
||||
|
||||
// Set up the API endpoints
|
||||
bind(ExtensionRESTService.class);
|
||||
bind(LanguageRESTService.class);
|
||||
bind(PatchRESTService.class);
|
||||
bind(TokenRESTService.class);
|
||||
|
||||
// Root-level resources
|
||||
bind(SessionRESTService.class);
|
||||
install(new FactoryModuleBuilder().build(SessionResourceFactory.class));
|
||||
install(new FactoryModuleBuilder().build(TunnelCollectionResourceFactory.class));
|
||||
install(new FactoryModuleBuilder().build(TunnelResourceFactory.class));
|
||||
@@ -108,10 +93,12 @@ public class RESTServiceModule extends ServletModule {
|
||||
install(new UserModule());
|
||||
install(new UserGroupModule());
|
||||
|
||||
// Set up the servlet and JSON mappings
|
||||
bind(GuiceContainer.class);
|
||||
bind(JacksonJsonProvider.class).in(Scopes.SINGLETON);
|
||||
serve("/api/*").with(GuiceContainer.class);
|
||||
// Serve REST services using Jersey 2.x
|
||||
bind(ServletContainer.class).in(Scopes.SINGLETON);
|
||||
serve("/api/*").with(ServletContainer.class, Collections.singletonMap(
|
||||
ServletProperties.JAXRS_APPLICATION_CLASS,
|
||||
GuacamoleApplication.class.getName()
|
||||
));
|
||||
|
||||
// Serve Webjar JavaScript dependencies
|
||||
bind(WebjarsServlet.class).in(Scopes.SINGLETON);
|
||||
|
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF 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.apache.guacamole.rest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.ws.rs.container.ContainerRequestContext;
|
||||
import javax.ws.rs.container.ContainerRequestFilter;
|
||||
import javax.ws.rs.container.ResourceInfo;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.ext.Provider;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.environment.Environment;
|
||||
import org.apache.guacamole.properties.LongGuacamoleProperty;
|
||||
|
||||
/**
|
||||
* Filter which restricts REST API requests to a particular maximum size.
|
||||
*/
|
||||
@Singleton
|
||||
@Provider
|
||||
public class RequestSizeFilter implements ContainerRequestFilter {
|
||||
|
||||
/**
|
||||
* Informs the RequestSizeFilter to NOT enforce its request size limits on
|
||||
* requests serviced by the annotated method.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public static @interface DoNotLimit {}
|
||||
|
||||
/**
|
||||
* The default maximum number of bytes to accept within the entity body of
|
||||
* any particular REST request.
|
||||
*/
|
||||
private final long DEFAULT_MAX_REQUEST_SIZE = 2097152;
|
||||
|
||||
/**
|
||||
* The maximum number of bytes to accept within the entity body of any
|
||||
* particular REST request. If not specified, requests will be limited to
|
||||
* 2 MB by default. Specifying 0 disables request size limitations.
|
||||
*/
|
||||
private final LongGuacamoleProperty API_MAX_REQUEST_SIZE = new LongGuacamoleProperty() {
|
||||
|
||||
@Override
|
||||
public String getName() { return "api-max-request-size"; }
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* The Guacamole server environment.
|
||||
*/
|
||||
@Inject
|
||||
private Environment environment;
|
||||
|
||||
/**
|
||||
* Information describing the resource that was requested.
|
||||
*/
|
||||
@Context
|
||||
private ResourceInfo resourceInfo;
|
||||
|
||||
@Override
|
||||
public void filter(ContainerRequestContext context) throws IOException {
|
||||
|
||||
// Retrieve configured request size limits
|
||||
final long maxRequestSize;
|
||||
try {
|
||||
maxRequestSize = environment.getProperty(API_MAX_REQUEST_SIZE, DEFAULT_MAX_REQUEST_SIZE);
|
||||
}
|
||||
catch (GuacamoleException e) {
|
||||
throw new APIException(e);
|
||||
}
|
||||
|
||||
// Ignore request size if limit is disabled
|
||||
if (maxRequestSize == 0 || resourceInfo.getResourceMethod().isAnnotationPresent(DoNotLimit.class))
|
||||
return;
|
||||
|
||||
// Restrict maximum size of requests which have an input stream
|
||||
// available to be limited
|
||||
InputStream stream = context.getEntityStream();
|
||||
if (stream != null)
|
||||
context.setEntityStream(new LimitedRequestInputStream(stream, maxRequestSize));
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -19,9 +19,9 @@
|
||||
|
||||
package org.apache.guacamole.rest.activeconnection;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import com.google.inject.assistedinject.AssistedInject;
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
|
@@ -19,10 +19,10 @@
|
||||
|
||||
package org.apache.guacamole.rest.auth;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.inject.Inject;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
|
@@ -19,9 +19,9 @@
|
||||
|
||||
package org.apache.guacamole.rest.auth;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||
|
@@ -20,10 +20,10 @@
|
||||
package org.apache.guacamole.rest.auth;
|
||||
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import com.google.inject.Inject;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.FormParam;
|
||||
|
@@ -19,10 +19,10 @@
|
||||
|
||||
package org.apache.guacamole.rest.connection;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import com.google.inject.assistedinject.AssistedInject;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
|
@@ -25,6 +25,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.PATCH;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
@@ -44,7 +45,6 @@ import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
|
||||
import org.apache.guacamole.net.auth.permission.SystemPermission;
|
||||
import org.apache.guacamole.net.auth.permission.SystemPermissionSet;
|
||||
import org.apache.guacamole.rest.APIPatch;
|
||||
import org.apache.guacamole.rest.PATCH;
|
||||
|
||||
/**
|
||||
* A REST resource which abstracts the operations available on all Guacamole
|
||||
|
@@ -20,7 +20,7 @@
|
||||
package org.apache.guacamole.rest.event;
|
||||
|
||||
import java.util.List;
|
||||
import com.google.inject.Inject;
|
||||
import javax.inject.Inject;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.net.event.listener.Listener;
|
||||
|
||||
|
@@ -19,8 +19,8 @@
|
||||
|
||||
package org.apache.guacamole.rest.extension;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
|
@@ -109,10 +109,7 @@ public class APISortPredicate {
|
||||
|
||||
// Bail out if sort property is not valid
|
||||
catch (IllegalArgumentException e) {
|
||||
throw new APIException(
|
||||
Response.Status.BAD_REQUEST,
|
||||
new GuacamoleClientException(String.format("Invalid sort property: \"%s\"", value))
|
||||
);
|
||||
throw new APIException(new GuacamoleClientException(String.format("Invalid sort property: \"%s\"", value)));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -23,13 +23,13 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.PATCH;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import org.apache.guacamole.GuacamoleClientException;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.net.auth.RelatedObjectSet;
|
||||
import org.apache.guacamole.rest.APIPatch;
|
||||
import org.apache.guacamole.rest.PATCH;
|
||||
|
||||
/**
|
||||
* A REST resource which abstracts the operations available on arbitrary sets
|
||||
|
@@ -19,8 +19,8 @@
|
||||
|
||||
package org.apache.guacamole.rest.language;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
|
@@ -19,12 +19,12 @@
|
||||
|
||||
package org.apache.guacamole.rest.patch;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
|
@@ -22,6 +22,7 @@ package org.apache.guacamole.rest.permission;
|
||||
import java.util.List;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.PATCH;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import org.apache.guacamole.GuacamoleClientException;
|
||||
@@ -31,7 +32,6 @@ import org.apache.guacamole.net.auth.permission.ObjectPermission;
|
||||
import org.apache.guacamole.net.auth.permission.Permission;
|
||||
import org.apache.guacamole.net.auth.permission.SystemPermission;
|
||||
import org.apache.guacamole.rest.APIPatch;
|
||||
import org.apache.guacamole.rest.PATCH;
|
||||
|
||||
/**
|
||||
* A REST resource which abstracts the operations available on the permissions
|
||||
|
@@ -19,7 +19,7 @@
|
||||
|
||||
package org.apache.guacamole.rest.session;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
|
@@ -19,9 +19,9 @@
|
||||
|
||||
package org.apache.guacamole.rest.session;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import com.google.inject.assistedinject.AssistedInject;
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
|
@@ -21,9 +21,9 @@ package org.apache.guacamole.rest.session;
|
||||
|
||||
import org.apache.guacamole.rest.directory.DirectoryResource;
|
||||
import org.apache.guacamole.rest.directory.DirectoryResourceFactory;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import com.google.inject.assistedinject.AssistedInject;
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
|
@@ -31,6 +31,7 @@ import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.ResponseBuilder;
|
||||
import javax.ws.rs.core.StreamingOutput;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.rest.RequestSizeFilter;
|
||||
import org.apache.guacamole.tunnel.StreamInterceptingTunnel;
|
||||
|
||||
/**
|
||||
@@ -127,6 +128,7 @@ public class StreamResource {
|
||||
*/
|
||||
@POST
|
||||
@Consumes(MediaType.WILDCARD)
|
||||
@RequestSizeFilter.DoNotLimit
|
||||
public void setStreamContents(InputStream data) throws GuacamoleException {
|
||||
|
||||
// Send input over stream
|
||||
|
@@ -19,11 +19,11 @@
|
||||
|
||||
package org.apache.guacamole.rest.tunnel;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import com.google.inject.assistedinject.AssistedInject;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
|
@@ -19,9 +19,9 @@
|
||||
|
||||
package org.apache.guacamole.rest.tunnel;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import com.google.inject.assistedinject.AssistedInject;
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
|
@@ -19,10 +19,10 @@
|
||||
|
||||
package org.apache.guacamole.tunnel;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.GuacamoleResourceNotFoundException;
|
||||
import org.apache.guacamole.GuacamoleSession;
|
||||
|
@@ -19,11 +19,10 @@
|
||||
|
||||
package org.apache.guacamole.tunnel.http;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.tunnel.TunnelRequestService;
|
||||
import org.apache.guacamole.net.GuacamoleTunnel;
|
||||
import org.apache.guacamole.servlet.GuacamoleHTTPTunnelServlet;
|
||||
|
@@ -19,8 +19,8 @@
|
||||
|
||||
package org.apache.guacamole.tunnel.websocket.jetty8;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.net.GuacamoleTunnel;
|
||||
import org.apache.guacamole.tunnel.TunnelRequestService;
|
||||
|
@@ -19,8 +19,8 @@
|
||||
|
||||
package org.apache.guacamole.tunnel.websocket.jetty9;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
|
||||
import org.apache.guacamole.tunnel.TunnelRequestService;
|
||||
|
@@ -19,8 +19,8 @@
|
||||
|
||||
package org.apache.guacamole.tunnel.websocket.tomcat;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.net.GuacamoleTunnel;
|
||||
import org.apache.guacamole.tunnel.TunnelRequestService;
|
||||
|
@@ -28,7 +28,7 @@
|
||||
<welcome-file>index.html</welcome-file>
|
||||
</welcome-file-list>
|
||||
|
||||
<!-- Guice -->
|
||||
<!-- Route all requests through Guice -->
|
||||
<filter>
|
||||
<filter-name>guiceFilter</filter-name>
|
||||
<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
|
||||
@@ -37,7 +37,6 @@
|
||||
<filter-name>guiceFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<listener>
|
||||
<listener-class>org.apache.guacamole.GuacamoleServletContextListener</listener-class>
|
||||
</listener>
|
||||
|
Reference in New Issue
Block a user