Skip to content

Commit

Permalink
Adds a VaadinFilter abstraction
Browse files Browse the repository at this point in the history
VaadinFilter simulates an around aspect around processing of a request

related to vaadingh-17436
  • Loading branch information
marcingrzejszczak committed Aug 25, 2023
1 parent c0803fb commit a327e3b
Show file tree
Hide file tree
Showing 8 changed files with 314 additions and 125 deletions.
55 changes: 55 additions & 0 deletions flow-server/src/main/java/com/vaadin/flow/server/VaadinFilter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright 2000-2023 Vaadin Ltd.
*
* Licensed 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 com.vaadin.flow.server;

import java.io.Serializable;

/**
* Used to provide an around-like aspect option around request processing.
*
* @author Marcin Grzejszczak
* @since 24.2
*/
public interface VaadinFilter extends Serializable {

/**
* Called when request is about to be processed.
* @param request request
* @param response response
*/
void requestStart(VaadinRequest request, VaadinResponse response);

/**
* Called when an exception occurred
* @param request request
* @param response response
* @param vaadinSession session
* @param t exception
*/
void handleException(VaadinRequest request,
VaadinResponse response, VaadinSession vaadinSession, Exception t);

/**
* Called in the finally block of processing a request. Will be called
* regardless of whether there was an exception or not.
* @param request request
* @param response response
* @param session session
*/
void requestEnd(VaadinRequest request, VaadinResponse response,
VaadinSession session);
}
86 changes: 38 additions & 48 deletions flow-server/src/main/java/com/vaadin/flow/server/VaadinService.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,41 +16,6 @@

package com.vaadin.flow.server;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.vaadin.flow.component.UI;
import com.vaadin.flow.di.DefaultInstantiator;
import com.vaadin.flow.di.Instantiator;
Expand All @@ -64,26 +29,30 @@
import com.vaadin.flow.router.RouteData;
import com.vaadin.flow.router.Router;
import com.vaadin.flow.server.HandlerHelper.RequestType;
import com.vaadin.flow.server.communication.AtmospherePushConnection;
import com.vaadin.flow.server.communication.HeartbeatHandler;
import com.vaadin.flow.server.communication.IndexHtmlRequestListener;
import com.vaadin.flow.server.communication.IndexHtmlResponse;
import com.vaadin.flow.server.communication.JavaScriptBootstrapHandler;
import com.vaadin.flow.server.communication.PwaHandler;
import com.vaadin.flow.server.communication.SessionRequestHandler;
import com.vaadin.flow.server.communication.StreamRequestHandler;
import com.vaadin.flow.server.communication.UidlRequestHandler;
import com.vaadin.flow.server.communication.WebComponentBootstrapHandler;
import com.vaadin.flow.server.communication.WebComponentProvider;
import com.vaadin.flow.server.communication.*;
import com.vaadin.flow.shared.ApplicationConstants;
import com.vaadin.flow.shared.JsonConstants;
import com.vaadin.flow.shared.Registration;
import com.vaadin.flow.shared.communication.PushMode;

import elemental.json.Json;
import elemental.json.JsonException;
import elemental.json.JsonObject;
import elemental.json.impl.JsonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

import static java.nio.charset.StandardCharsets.UTF_8;

Expand Down Expand Up @@ -114,6 +83,8 @@ public abstract class VaadinService implements Serializable {
+ PushMode.class.getSimpleName() + "." + PushMode.DISABLED.name()
+ "." + SEPARATOR;

private List<VaadinFilter> vaadinFilters = new ArrayList<>();

/**
* Attribute name for telling
* {@link VaadinSession#valueUnbound(jakarta.servlet.http.HttpSessionBindingEvent)}
Expand Down Expand Up @@ -1433,6 +1404,7 @@ public void requestStart(VaadinRequest request, VaadinResponse response) {
}
setCurrentInstances(request, response);
request.setAttribute(REQUEST_START_TIME_ATTRIBUTE, System.nanoTime());
vaadinFilters.forEach(vaadinFilter -> vaadinFilter.requestStart(request, response));
}

/**
Expand All @@ -1449,6 +1421,7 @@ public void requestStart(VaadinRequest request, VaadinResponse response) {
*/
public void requestEnd(VaadinRequest request, VaadinResponse response,
VaadinSession session) {
vaadinFilters.forEach(vaadinFilter -> vaadinFilter.requestEnd(request, response, session));
if (session != null) {
assert VaadinSession.getCurrent() == session;
session.lock();
Expand Down Expand Up @@ -1544,6 +1517,15 @@ private void handleExceptionDuringRequest(VaadinRequest request,
vaadinSession.lock();
}
try {
try {
vaadinFilters.forEach(vaadinFilter -> vaadinFilter.handleException(request,
response, vaadinSession, t));
} catch (Exception ex) {
// An exception occurred while handling an exception. Log
// it and continue handling only the original error.
getLogger().warn(
"Failed to handle an exception using filters", ex);
}
if (vaadinSession != null) {
vaadinSession.getErrorHandler().error(new ErrorEvent(t));
}
Expand Down Expand Up @@ -2374,6 +2356,14 @@ public static String getCsrfTokenAttributeName() {
+ ApplicationConstants.CSRF_TOKEN;
}

public List<VaadinFilter> getVaadinFilters() {
return vaadinFilters;
}

public void setVaadinFilters(List<VaadinFilter> vaadinFilters) {
this.vaadinFilters = vaadinFilters;
}

private void doSetClassLoader() {
final String classLoaderName = getDeploymentConfiguration() == null
? null
Expand All @@ -2398,4 +2388,4 @@ private void doSetClassLoader() {
setDefaultClassLoader();
}
}
}
}
41 changes: 22 additions & 19 deletions flow-server/src/main/java/com/vaadin/flow/server/VaadinServlet.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,6 @@
*/
package com.vaadin.flow.server;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.vaadin.flow.component.UI;
import com.vaadin.flow.di.Lookup;
import com.vaadin.flow.function.DeploymentConfiguration;
Expand All @@ -37,14 +24,20 @@
import com.vaadin.flow.server.HandlerHelper.RequestType;
import com.vaadin.flow.server.startup.ApplicationConfiguration;
import com.vaadin.flow.shared.JsonConstants;

import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRegistration;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;

/**
* The main servlet, which handles all incoming requests to the application.
Expand Down Expand Up @@ -72,6 +65,8 @@ public class VaadinServlet extends HttpServlet {

private static List<Runnable> whenFrontendMappingAvailable = new ArrayList<>();

private List<VaadinFilter> vaadinFilters = new ArrayList<>();

/**
* Called by the servlet container to indicate to a servlet that the servlet
* is being placed into service.
Expand Down Expand Up @@ -589,9 +584,9 @@ static URL getApplicationUrl(HttpServletRequest request)
final URL reqURL = new URL((request.isSecure() ? "https://" : "http://")
+ request.getServerName()
+ ((request.isSecure() && request.getServerPort() == 443)
|| (!request.isSecure()
&& request.getServerPort() == 80) ? ""
: ":" + request.getServerPort())
|| (!request.isSecure()
&& request.getServerPort() == 80) ? ""
: ":" + request.getServerPort())
+ request.getRequestURI());
String servletPath;
if (request
Expand All @@ -601,7 +596,7 @@ static URL getApplicationUrl(HttpServletRequest request)
.getAttribute("jakarta.servlet.include.context_path")
.toString()
+ request.getAttribute(
"jakarta.servlet.include.servlet_path");
"jakarta.servlet.include.servlet_path");

} else {
servletPath = request.getContextPath() + request.getServletPath();
Expand Down Expand Up @@ -647,6 +642,14 @@ private VaadinServletContext initializeContext() {
return vaadinServletContext;
}

public List<VaadinFilter> getVaadinFilters() {
return vaadinFilters;
}

public void setVaadinFilters(List<VaadinFilter> vaadinFilters) {
this.vaadinFilters = vaadinFilters;
}

/**
* For internal use only.
*
Expand All @@ -656,4 +659,4 @@ public static String getFrontendMapping() {
return frontendMapping;
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,19 @@

package com.vaadin.flow.server;

import com.vaadin.flow.function.DeploymentConfiguration;
import com.vaadin.flow.internal.DevModeHandler;
import com.vaadin.flow.internal.DevModeHandlerManager;
import com.vaadin.flow.server.communication.FaviconHandler;
import com.vaadin.flow.server.communication.IndexHtmlRequestHandler;
import com.vaadin.flow.server.communication.PushRequestHandler;
import com.vaadin.flow.server.startup.ApplicationRouteRegistry;
import com.vaadin.flow.shared.ApplicationConstants;
import jakarta.servlet.GenericServlet;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.InputStream;
import java.net.MalformedURLException;
Expand All @@ -27,18 +37,6 @@
import java.util.Objects;
import java.util.Optional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.vaadin.flow.function.DeploymentConfiguration;
import com.vaadin.flow.internal.DevModeHandler;
import com.vaadin.flow.internal.DevModeHandlerManager;
import com.vaadin.flow.server.communication.FaviconHandler;
import com.vaadin.flow.server.communication.IndexHtmlRequestHandler;
import com.vaadin.flow.server.communication.PushRequestHandler;
import com.vaadin.flow.server.startup.ApplicationRouteRegistry;
import com.vaadin.flow.shared.ApplicationConstants;

/**
* A service implementation connected to a {@link VaadinServlet}.
*
Expand Down Expand Up @@ -66,6 +64,9 @@ public VaadinServletService(VaadinServlet servlet,
DeploymentConfiguration deploymentConfiguration) {
super(deploymentConfiguration);
this.servlet = servlet;
if (servlet != null) {
setVaadinFilters(servlet.getVaadinFilters());
}
}

/**
Expand Down Expand Up @@ -157,7 +158,7 @@ private boolean isOtherRequest(VaadinRequest request) {
return type == null
|| ApplicationConstants.REQUEST_TYPE_INIT.equals(type)
|| ApplicationConstants.REQUEST_TYPE_WEBCOMPONENT_RESYNC
.equals(type);
.equals(type);
}

public static HttpServletRequest getCurrentServletRequest() {
Expand Down Expand Up @@ -306,4 +307,4 @@ protected VaadinContext constructVaadinContext() {
protected void setDefaultClassLoader() {
setClassLoader(getServlet().getServletContext().getClassLoader());
}
}
}
Loading

0 comments on commit a327e3b

Please sign in to comment.