-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
395606 Move Servlet/ServletFilters from StART to Scout
- Loading branch information
Showing
11 changed files
with
457 additions
and
0 deletions.
There are no files selected for viewing
89 changes: 89 additions & 0 deletions
89
org.eclipse.scout.rt.app/src/main/java/org/eclipse/scout/rt/app/filter/ExceptionFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
/* | ||
* Copyright (c) BSI Business Systems Integration AG. All rights reserved. | ||
* http://www.bsiag.com/ | ||
*/ | ||
package org.eclipse.scout.rt.app.filter; | ||
|
||
import java.io.IOException; | ||
|
||
import jakarta.servlet.Filter; | ||
import jakarta.servlet.FilterChain; | ||
import jakarta.servlet.FilterConfig; | ||
import jakarta.servlet.ServletException; | ||
import jakarta.servlet.ServletRequest; | ||
import jakarta.servlet.ServletResponse; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
|
||
import org.eclipse.jetty.io.QuietException; | ||
import org.eclipse.jetty.server.HttpChannel; | ||
import org.eclipse.scout.rt.platform.context.CorrelationId; | ||
import org.eclipse.scout.rt.platform.context.CorrelationIdContextValueProvider; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.slf4j.MDC; | ||
|
||
/** | ||
* Filter that catches Exceptions thrown by consecutive filters or servlet and that logs them along with the correlation | ||
* id if available. Logging the correlation id is the main difference to the logging otherwise performed by Jetty. | ||
*/ | ||
public class ExceptionFilter implements Filter { | ||
|
||
private static final Logger LOG = LoggerFactory.getLogger(ExceptionFilter.class); | ||
|
||
@Override | ||
public void init(FilterConfig filterConfig) { | ||
// nothing to initialize | ||
} | ||
|
||
@Override | ||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { | ||
try { | ||
chain.doFilter(request, response); | ||
} | ||
catch (Exception e) { | ||
if (isCausedByQuietException(e)) { | ||
throw e; | ||
} | ||
|
||
HttpServletRequest req = (HttpServletRequest) request; | ||
MDC.put(CorrelationIdContextValueProvider.KEY, req.getHeader(CorrelationId.HTTP_HEADER_NAME)); | ||
try { | ||
LOG.warn(req.getRequestURI(), e); | ||
} | ||
finally { | ||
MDC.remove(CorrelationIdContextValueProvider.KEY); | ||
} | ||
throw new JettyQuietExceptionWrapper(e); | ||
} | ||
} | ||
|
||
/** | ||
* @return {@code true} if the given Throwable is a {@link QuietException} or wraps one. Otherwise {@code false}. | ||
*/ | ||
protected boolean isCausedByQuietException(Throwable t) { | ||
Throwable cur = t; | ||
while (cur != null) { | ||
// QuietException is a marker to use less verbosely logging | ||
if (cur instanceof QuietException) { | ||
return true; | ||
} | ||
cur = cur.getCause(); | ||
} | ||
return false; | ||
} | ||
|
||
@Override | ||
public void destroy() { | ||
} | ||
|
||
/** | ||
* {@link QuietException}s are not logged by Jetty unless the log level of {@link HttpChannel} is DEBUG. | ||
*/ | ||
public static class JettyQuietExceptionWrapper extends RuntimeException implements QuietException { | ||
private static final long serialVersionUID = 1L; | ||
|
||
public JettyQuietExceptionWrapper(Throwable cause) { | ||
super(cause); | ||
} | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
org.eclipse.scout.rt.rest/src/main/java/org/eclipse/scout/rt/rest/log/NoLog.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/* | ||
* Copyright (c) BSI Business Systems Integration AG. All rights reserved. | ||
* http://www.bsiag.com/ | ||
*/ | ||
package org.eclipse.scout.rt.rest.log; | ||
|
||
import static java.lang.annotation.ElementType.*; | ||
import static java.lang.annotation.RetentionPolicy.RUNTIME; | ||
|
||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.Target; | ||
|
||
/** | ||
* Specifies that REST calls to the annotated target should not be logged to the application's <i>access log</i>. | ||
*/ | ||
@Target({TYPE, METHOD}) | ||
@Retention(RUNTIME) | ||
public @interface NoLog { | ||
|
||
/** | ||
* @return <code>true</code> to disable logging for this target. This is the default value. It can be set to | ||
* <code>false</code> to re-enable the logging. | ||
*/ | ||
boolean value() default true; | ||
} |
51 changes: 51 additions & 0 deletions
51
org.eclipse.scout.rt.rest/src/main/java/org/eclipse/scout/rt/rest/log/NoLogFeature.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/* | ||
* Copyright (c) BSI Business Systems Integration AG. All rights reserved. | ||
* http://www.bsiag.com/ | ||
*/ | ||
package org.eclipse.scout.rt.rest.log; | ||
|
||
import java.util.Collections; | ||
import java.util.Set; | ||
|
||
import jakarta.ws.rs.container.DynamicFeature; | ||
import jakarta.ws.rs.container.ResourceInfo; | ||
import jakarta.ws.rs.core.FeatureContext; | ||
|
||
import org.eclipse.scout.rt.rest.RestApplication.IRestApplicationClassesContributor; | ||
|
||
/** | ||
* Installs the {@link NoLogFilter} for all REST methods that are annotated with @{@link NoLog}. | ||
*/ | ||
public class NoLogFeature implements DynamicFeature { | ||
|
||
@Override | ||
public void configure(ResourceInfo resourceInfo, FeatureContext context) { | ||
NoLog noLogAnnotationMethod = resourceInfo.getResourceMethod().getAnnotation(NoLog.class); | ||
NoLog noLogAnnotationClass = resourceInfo.getResourceClass().getAnnotation(NoLog.class); | ||
|
||
// Compute if logging is disabled | ||
boolean noLog = false; | ||
if (noLogAnnotationMethod != null) { | ||
noLog = noLogAnnotationMethod.value(); | ||
} | ||
else if (noLogAnnotationClass != null) { | ||
noLog = noLogAnnotationClass.value(); | ||
} | ||
|
||
// If not loggable, install a filter that sets the "NoLog" attribute | ||
if (noLog) { | ||
context.register(NoLogFilter.class); | ||
} | ||
} | ||
|
||
/** | ||
* Installs the {@link NoLogFilter} into the REST application. | ||
*/ | ||
public static class NoLogFilterFeatureContributor implements IRestApplicationClassesContributor { | ||
|
||
@Override | ||
public Set<Class<?>> contribute() { | ||
return Collections.singleton(NoLogFeature.class); | ||
} | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
org.eclipse.scout.rt.rest/src/main/java/org/eclipse/scout/rt/rest/log/NoLogFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/* | ||
* Copyright (c) BSI Business Systems Integration AG. All rights reserved. | ||
* http://www.bsiag.com/ | ||
*/ | ||
//FIXME | ||
package org.eclipse.scout.rt.rest.log; | ||
|
||
import java.io.IOException; | ||
|
||
import jakarta.ws.rs.container.ContainerRequestContext; | ||
import jakarta.ws.rs.container.ContainerRequestFilter; | ||
|
||
/** | ||
* Dynamically installed request filter that sets the {@link #REQUEST_ATTRIBUTE} flag. | ||
*/ | ||
public class NoLogFilter implements ContainerRequestFilter { | ||
|
||
/** | ||
* Name of the attribute that is set to the current request by {@link NoLogFilter}. The attribute value is irrelevant. | ||
*/ | ||
public static final String REQUEST_ATTRIBUTE = NoLogFilter.class.getName(); | ||
|
||
@Override | ||
public void filter(ContainerRequestContext requestContext) throws IOException { | ||
requestContext.setProperty(REQUEST_ATTRIBUTE, "X"); | ||
} | ||
} |
60 changes: 60 additions & 0 deletions
60
...clipse.scout.rt.rest/src/main/java/org/eclipse/scout/rt/rest/resource/ResourceHelper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/* | ||
* Copyright (c) BSI Business Systems Integration AG. All rights reserved. | ||
* http://www.bsiag.com/ | ||
*/ | ||
package org.eclipse.scout.rt.rest.resource; | ||
|
||
import java.io.InputStream; | ||
|
||
import jakarta.ws.rs.core.CacheControl; | ||
import jakarta.ws.rs.core.Response; | ||
|
||
import org.eclipse.scout.rt.platform.ApplicationScoped; | ||
import org.eclipse.scout.rt.platform.util.IOUtility; | ||
import org.eclipse.scout.rt.platform.util.ObjectUtility; | ||
|
||
/** | ||
* Helper class used by REST resources. | ||
*/ | ||
@ApplicationScoped | ||
public class ResourceHelper { | ||
|
||
public static final String IMAGE_TYPES = "image/jpeg, image/gif, image/png"; | ||
public static final String ZIP_TYPE = "application/zip"; | ||
|
||
/** | ||
* Creates a response with streaming binary data and no-cache headers. Use this method to return large data / files. | ||
*/ | ||
// FIXME sme check for occurrences of this header and replace by new utility (source from DownloadHttpResponseInterceptor.calcContentDispositionHeaderValue(String)). | ||
public Response binaryResponse(InputStream in, String filename, String mimeType) { | ||
return Response.ok(in, mimeType) | ||
.header("Content-Disposition", "attachment; filename*=utf-8''" + IOUtility.urlEncode(filename)) | ||
.cacheControl(createNoCacheControl()) | ||
.build(); | ||
} | ||
|
||
/** | ||
* Creates a response with binary data and no-cache headers. | ||
*/ | ||
public Response binaryResponse(byte[] data, String mimeType) { | ||
return binaryResponse(data, mimeType, null); | ||
} | ||
|
||
/** | ||
* Creates a response with binary data and cache-control headers. | ||
*/ | ||
public Response binaryResponse(byte[] data, String mimeType, CacheControl cacheControl) { | ||
cacheControl = ObjectUtility.nvlOpt(cacheControl, this::createNoCacheControl); | ||
return Response.ok(data, mimeType) | ||
.cacheControl(cacheControl) | ||
.build(); | ||
} | ||
|
||
public CacheControl createNoCacheControl() { | ||
CacheControl cc = new CacheControl(); | ||
cc.setNoCache(true); | ||
cc.setMustRevalidate(true); | ||
cc.setNoStore(true); | ||
return cc; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
22 changes: 22 additions & 0 deletions
22
...commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/ApiRestApplication.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/* | ||
* Copyright (c) BSI Business Systems Integration AG. All rights reserved. | ||
* http://www.bsiag.com/ | ||
*/ | ||
package org.eclipse.scout.rt.server.commons.servlet; | ||
|
||
import org.eclipse.scout.rt.platform.util.ObjectUtility; | ||
import org.eclipse.scout.rt.rest.RestApplication; | ||
import org.eclipse.scout.rt.rest.RestApplicationScope; | ||
import org.eclipse.scout.rt.rest.RestApplicationScopes; | ||
|
||
/** | ||
* @see RestApplicationScopes#API | ||
*/ | ||
public class ApiRestApplication extends RestApplication { | ||
|
||
@Override | ||
protected boolean filterClass(Class<?> clazz) { | ||
RestApplicationScope annotation = clazz.getAnnotation(RestApplicationScope.class); | ||
return annotation == null || ObjectUtility.isOneOf(RestApplicationScopes.API, annotation.value()); | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
...commons/src/main/java/org/eclipse/scout/rt/server/commons/servlet/ExtRestApplication.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/* | ||
* Copyright (c) BSI Business Systems Integration AG. All rights reserved. | ||
* http://www.bsiag.com/ | ||
*/ | ||
package org.eclipse.scout.rt.server.commons.servlet; | ||
|
||
import org.eclipse.scout.rt.platform.util.ObjectUtility; | ||
import org.eclipse.scout.rt.rest.IRestResource; | ||
import org.eclipse.scout.rt.rest.RestApplication; | ||
import org.eclipse.scout.rt.rest.RestApplicationScope; | ||
import org.eclipse.scout.rt.rest.RestApplicationScopes; | ||
import org.eclipse.scout.rt.rest.container.AntiCsrfContainerFilter; | ||
|
||
/** | ||
* @see RestApplicationScopes#EXT | ||
*/ | ||
public class ExtRestApplication extends RestApplication { | ||
|
||
@Override | ||
protected boolean filterClass(Class<?> clazz) { | ||
return !AntiCsrfContainerFilter.class.isAssignableFrom(clazz) | ||
&& (!IRestResource.class.isAssignableFrom(clazz) || isExtScope(clazz)); | ||
} | ||
|
||
protected boolean isExtScope(Class<?> clazz) { | ||
RestApplicationScope annotation = clazz.getAnnotation(RestApplicationScope.class); | ||
return annotation != null && ObjectUtility.isOneOf(RestApplicationScopes.EXT, annotation.value()); | ||
} | ||
} |
59 changes: 59 additions & 0 deletions
59
...n/java/org/eclipse/scout/rt/server/commons/servlet/filter/EnforceNoHttpSessionFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/* | ||
* Copyright (c) BSI Business Systems Integration AG. All rights reserved. | ||
* http://www.bsiag.com/ | ||
*/ | ||
package org.eclipse.scout.rt.server.commons.servlet.filter; | ||
|
||
import java.io.IOException; | ||
|
||
import jakarta.servlet.Filter; | ||
import jakarta.servlet.FilterChain; | ||
import jakarta.servlet.FilterConfig; | ||
import jakarta.servlet.ServletException; | ||
import jakarta.servlet.ServletRequest; | ||
import jakarta.servlet.ServletResponse; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletRequestWrapper; | ||
import jakarta.servlet.http.HttpSession; | ||
|
||
public class EnforceNoHttpSessionFilter implements Filter { | ||
|
||
@Override | ||
public void init(FilterConfig filterConfig) { | ||
// nothing to initialize | ||
} | ||
|
||
@Override | ||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { | ||
chain.doFilter(wrapRequest(request), response); | ||
} | ||
|
||
@Override | ||
public void destroy() { | ||
// nothing to destroy | ||
} | ||
|
||
protected HttpServletRequest wrapRequest(ServletRequest request) { | ||
return new SessionlessHttpServletRequestWrapper((HttpServletRequest) request); | ||
} | ||
|
||
public static class SessionlessHttpServletRequestWrapper extends HttpServletRequestWrapper { | ||
|
||
public SessionlessHttpServletRequestWrapper(HttpServletRequest request) { | ||
super(request); | ||
} | ||
|
||
@Override | ||
public HttpSession getSession() { | ||
throw new UnsupportedOperationException("HTTP session not allowed"); | ||
} | ||
|
||
@Override | ||
public HttpSession getSession(boolean create) { | ||
if (!create) { | ||
return null; | ||
} | ||
throw new UnsupportedOperationException("HTTP session not allowed"); | ||
} | ||
} | ||
} |
Oops, something went wrong.