Skip to content

Commit 134785c

Browse files
Adds a VaadinFilter abstraction
VaadinFilter simulates an around aspect around processing of a request related to vaadingh-17436
1 parent 74196a0 commit 134785c

File tree

8 files changed

+314
-125
lines changed

8 files changed

+314
-125
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright 2000-2023 Vaadin Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
17+
package com.vaadin.flow.server;
18+
19+
import java.io.Serializable;
20+
21+
/**
22+
* Used to provide an around-like aspect option around request processing.
23+
*
24+
* @author Marcin Grzejszczak
25+
* @since 24.2
26+
*/
27+
public interface VaadinFilter extends Serializable {
28+
29+
/**
30+
* Called when request is about to be processed.
31+
* @param request request
32+
* @param response response
33+
*/
34+
void requestStart(VaadinRequest request, VaadinResponse response);
35+
36+
/**
37+
* Called when an exception occurred
38+
* @param request request
39+
* @param response response
40+
* @param vaadinSession session
41+
* @param t exception
42+
*/
43+
void handleException(VaadinRequest request,
44+
VaadinResponse response, VaadinSession vaadinSession, Exception t);
45+
46+
/**
47+
* Called in the finally block of processing a request. Will be called
48+
* regardless of whether there was an exception or not.
49+
* @param request request
50+
* @param response response
51+
* @param session session
52+
*/
53+
void requestEnd(VaadinRequest request, VaadinResponse response,
54+
VaadinSession session);
55+
}

flow-server/src/main/java/com/vaadin/flow/server/VaadinService.java

+38-48
Original file line numberDiff line numberDiff line change
@@ -16,41 +16,6 @@
1616

1717
package com.vaadin.flow.server;
1818

19-
import java.io.BufferedWriter;
20-
import java.io.IOException;
21-
import java.io.InputStream;
22-
import java.io.OutputStream;
23-
import java.io.OutputStreamWriter;
24-
import java.io.PrintWriter;
25-
import java.io.Serializable;
26-
import java.lang.reflect.Constructor;
27-
import java.net.URL;
28-
import java.nio.charset.StandardCharsets;
29-
import java.security.MessageDigest;
30-
import java.util.ArrayList;
31-
import java.util.Collection;
32-
import java.util.Collections;
33-
import java.util.HashMap;
34-
import java.util.List;
35-
import java.util.Locale;
36-
import java.util.Map;
37-
import java.util.Map.Entry;
38-
import java.util.Optional;
39-
import java.util.ServiceLoader;
40-
import java.util.Set;
41-
import java.util.concurrent.CancellationException;
42-
import java.util.concurrent.ConcurrentHashMap;
43-
import java.util.concurrent.CopyOnWriteArrayList;
44-
import java.util.concurrent.Future;
45-
import java.util.concurrent.TimeUnit;
46-
import java.util.concurrent.locks.Lock;
47-
import java.util.concurrent.locks.ReentrantLock;
48-
import java.util.stream.Collectors;
49-
import java.util.stream.StreamSupport;
50-
51-
import org.slf4j.Logger;
52-
import org.slf4j.LoggerFactory;
53-
5419
import com.vaadin.flow.component.UI;
5520
import com.vaadin.flow.di.DefaultInstantiator;
5621
import com.vaadin.flow.di.Instantiator;
@@ -64,26 +29,30 @@
6429
import com.vaadin.flow.router.RouteData;
6530
import com.vaadin.flow.router.Router;
6631
import com.vaadin.flow.server.HandlerHelper.RequestType;
67-
import com.vaadin.flow.server.communication.AtmospherePushConnection;
68-
import com.vaadin.flow.server.communication.HeartbeatHandler;
69-
import com.vaadin.flow.server.communication.IndexHtmlRequestListener;
70-
import com.vaadin.flow.server.communication.IndexHtmlResponse;
71-
import com.vaadin.flow.server.communication.JavaScriptBootstrapHandler;
72-
import com.vaadin.flow.server.communication.PwaHandler;
73-
import com.vaadin.flow.server.communication.SessionRequestHandler;
74-
import com.vaadin.flow.server.communication.StreamRequestHandler;
75-
import com.vaadin.flow.server.communication.UidlRequestHandler;
76-
import com.vaadin.flow.server.communication.WebComponentBootstrapHandler;
77-
import com.vaadin.flow.server.communication.WebComponentProvider;
32+
import com.vaadin.flow.server.communication.*;
7833
import com.vaadin.flow.shared.ApplicationConstants;
7934
import com.vaadin.flow.shared.JsonConstants;
8035
import com.vaadin.flow.shared.Registration;
8136
import com.vaadin.flow.shared.communication.PushMode;
82-
8337
import elemental.json.Json;
8438
import elemental.json.JsonException;
8539
import elemental.json.JsonObject;
8640
import elemental.json.impl.JsonUtil;
41+
import org.slf4j.Logger;
42+
import org.slf4j.LoggerFactory;
43+
44+
import java.io.*;
45+
import java.lang.reflect.Constructor;
46+
import java.net.URL;
47+
import java.nio.charset.StandardCharsets;
48+
import java.security.MessageDigest;
49+
import java.util.*;
50+
import java.util.Map.Entry;
51+
import java.util.concurrent.*;
52+
import java.util.concurrent.locks.Lock;
53+
import java.util.concurrent.locks.ReentrantLock;
54+
import java.util.stream.Collectors;
55+
import java.util.stream.StreamSupport;
8756

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

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

86+
private List<VaadinFilter> vaadinFilters = new ArrayList<>();
87+
11788
/**
11889
* Attribute name for telling
11990
* {@link VaadinSession#valueUnbound(jakarta.servlet.http.HttpSessionBindingEvent)}
@@ -1433,6 +1404,7 @@ public void requestStart(VaadinRequest request, VaadinResponse response) {
14331404
}
14341405
setCurrentInstances(request, response);
14351406
request.setAttribute(REQUEST_START_TIME_ATTRIBUTE, System.nanoTime());
1407+
vaadinFilters.forEach(vaadinFilter -> vaadinFilter.requestStart(request, response));
14361408
}
14371409

14381410
/**
@@ -1449,6 +1421,7 @@ public void requestStart(VaadinRequest request, VaadinResponse response) {
14491421
*/
14501422
public void requestEnd(VaadinRequest request, VaadinResponse response,
14511423
VaadinSession session) {
1424+
vaadinFilters.forEach(vaadinFilter -> vaadinFilter.requestEnd(request, response, session));
14521425
if (session != null) {
14531426
assert VaadinSession.getCurrent() == session;
14541427
session.lock();
@@ -1544,6 +1517,15 @@ private void handleExceptionDuringRequest(VaadinRequest request,
15441517
vaadinSession.lock();
15451518
}
15461519
try {
1520+
try {
1521+
vaadinFilters.forEach(vaadinFilter -> vaadinFilter.handleException(request,
1522+
response, vaadinSession, t));
1523+
} catch (Exception ex) {
1524+
// An exception occurred while handling an exception. Log
1525+
// it and continue handling only the original error.
1526+
getLogger().warn(
1527+
"Failed to handle an exception using filters", ex);
1528+
}
15471529
if (vaadinSession != null) {
15481530
vaadinSession.getErrorHandler().error(new ErrorEvent(t));
15491531
}
@@ -2374,6 +2356,14 @@ public static String getCsrfTokenAttributeName() {
23742356
+ ApplicationConstants.CSRF_TOKEN;
23752357
}
23762358

2359+
public List<VaadinFilter> getVaadinFilters() {
2360+
return vaadinFilters;
2361+
}
2362+
2363+
public void setVaadinFilters(List<VaadinFilter> vaadinFilters) {
2364+
this.vaadinFilters = vaadinFilters;
2365+
}
2366+
23772367
private void doSetClassLoader() {
23782368
final String classLoaderName = getDeploymentConfiguration() == null
23792369
? null
@@ -2398,4 +2388,4 @@ private void doSetClassLoader() {
23982388
setDefaultClassLoader();
23992389
}
24002390
}
2401-
}
2391+
}

flow-server/src/main/java/com/vaadin/flow/server/VaadinServlet.java

+22-19
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,6 @@
1515
*/
1616
package com.vaadin.flow.server;
1717

18-
import java.io.IOException;
19-
import java.net.MalformedURLException;
20-
import java.net.URL;
21-
import java.util.ArrayList;
22-
import java.util.Collection;
23-
import java.util.Collections;
24-
import java.util.List;
25-
import java.util.Map;
26-
import java.util.Properties;
27-
28-
import org.slf4j.Logger;
29-
import org.slf4j.LoggerFactory;
30-
3118
import com.vaadin.flow.component.UI;
3219
import com.vaadin.flow.di.Lookup;
3320
import com.vaadin.flow.function.DeploymentConfiguration;
@@ -37,14 +24,20 @@
3724
import com.vaadin.flow.server.HandlerHelper.RequestType;
3825
import com.vaadin.flow.server.startup.ApplicationConfiguration;
3926
import com.vaadin.flow.shared.JsonConstants;
40-
4127
import jakarta.servlet.ServletConfig;
4228
import jakarta.servlet.ServletContext;
4329
import jakarta.servlet.ServletException;
4430
import jakarta.servlet.ServletRegistration;
4531
import jakarta.servlet.http.HttpServlet;
4632
import jakarta.servlet.http.HttpServletRequest;
4733
import jakarta.servlet.http.HttpServletResponse;
34+
import org.slf4j.Logger;
35+
import org.slf4j.LoggerFactory;
36+
37+
import java.io.IOException;
38+
import java.net.MalformedURLException;
39+
import java.net.URL;
40+
import java.util.*;
4841

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

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

68+
private List<VaadinFilter> vaadinFilters = new ArrayList<>();
69+
7570
/**
7671
* Called by the servlet container to indicate to a servlet that the servlet
7772
* is being placed into service.
@@ -589,9 +584,9 @@ static URL getApplicationUrl(HttpServletRequest request)
589584
final URL reqURL = new URL((request.isSecure() ? "https://" : "http://")
590585
+ request.getServerName()
591586
+ ((request.isSecure() && request.getServerPort() == 443)
592-
|| (!request.isSecure()
593-
&& request.getServerPort() == 80) ? ""
594-
: ":" + request.getServerPort())
587+
|| (!request.isSecure()
588+
&& request.getServerPort() == 80) ? ""
589+
: ":" + request.getServerPort())
595590
+ request.getRequestURI());
596591
String servletPath;
597592
if (request
@@ -601,7 +596,7 @@ static URL getApplicationUrl(HttpServletRequest request)
601596
.getAttribute("jakarta.servlet.include.context_path")
602597
.toString()
603598
+ request.getAttribute(
604-
"jakarta.servlet.include.servlet_path");
599+
"jakarta.servlet.include.servlet_path");
605600

606601
} else {
607602
servletPath = request.getContextPath() + request.getServletPath();
@@ -647,6 +642,14 @@ private VaadinServletContext initializeContext() {
647642
return vaadinServletContext;
648643
}
649644

645+
public List<VaadinFilter> getVaadinFilters() {
646+
return vaadinFilters;
647+
}
648+
649+
public void setVaadinFilters(List<VaadinFilter> vaadinFilters) {
650+
this.vaadinFilters = vaadinFilters;
651+
}
652+
650653
/**
651654
* For internal use only.
652655
*
@@ -656,4 +659,4 @@ public static String getFrontendMapping() {
656659
return frontendMapping;
657660
}
658661

659-
}
662+
}

flow-server/src/main/java/com/vaadin/flow/server/VaadinServletService.java

+15-14
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,19 @@
1616

1717
package com.vaadin.flow.server;
1818

19+
import com.vaadin.flow.function.DeploymentConfiguration;
20+
import com.vaadin.flow.internal.DevModeHandler;
21+
import com.vaadin.flow.internal.DevModeHandlerManager;
22+
import com.vaadin.flow.server.communication.FaviconHandler;
23+
import com.vaadin.flow.server.communication.IndexHtmlRequestHandler;
24+
import com.vaadin.flow.server.communication.PushRequestHandler;
25+
import com.vaadin.flow.server.startup.ApplicationRouteRegistry;
26+
import com.vaadin.flow.shared.ApplicationConstants;
1927
import jakarta.servlet.GenericServlet;
2028
import jakarta.servlet.ServletContext;
2129
import jakarta.servlet.http.HttpServletRequest;
30+
import org.slf4j.Logger;
31+
import org.slf4j.LoggerFactory;
2232

2333
import java.io.InputStream;
2434
import java.net.MalformedURLException;
@@ -27,18 +37,6 @@
2737
import java.util.Objects;
2838
import java.util.Optional;
2939

30-
import org.slf4j.Logger;
31-
import org.slf4j.LoggerFactory;
32-
33-
import com.vaadin.flow.function.DeploymentConfiguration;
34-
import com.vaadin.flow.internal.DevModeHandler;
35-
import com.vaadin.flow.internal.DevModeHandlerManager;
36-
import com.vaadin.flow.server.communication.FaviconHandler;
37-
import com.vaadin.flow.server.communication.IndexHtmlRequestHandler;
38-
import com.vaadin.flow.server.communication.PushRequestHandler;
39-
import com.vaadin.flow.server.startup.ApplicationRouteRegistry;
40-
import com.vaadin.flow.shared.ApplicationConstants;
41-
4240
/**
4341
* A service implementation connected to a {@link VaadinServlet}.
4442
*
@@ -66,6 +64,9 @@ public VaadinServletService(VaadinServlet servlet,
6664
DeploymentConfiguration deploymentConfiguration) {
6765
super(deploymentConfiguration);
6866
this.servlet = servlet;
67+
if (servlet != null) {
68+
setVaadinFilters(servlet.getVaadinFilters());
69+
}
6970
}
7071

7172
/**
@@ -157,7 +158,7 @@ private boolean isOtherRequest(VaadinRequest request) {
157158
return type == null
158159
|| ApplicationConstants.REQUEST_TYPE_INIT.equals(type)
159160
|| ApplicationConstants.REQUEST_TYPE_WEBCOMPONENT_RESYNC
160-
.equals(type);
161+
.equals(type);
161162
}
162163

163164
public static HttpServletRequest getCurrentServletRequest() {
@@ -306,4 +307,4 @@ protected VaadinContext constructVaadinContext() {
306307
protected void setDefaultClassLoader() {
307308
setClassLoader(getServlet().getServletContext().getClassLoader());
308309
}
309-
}
310+
}

0 commit comments

Comments
 (0)