装饰 Quarkus Amazon Lambda HTTP 扩展中的所有 RESTEasy 反应式请求处理

问题描述 投票:0回答:1

我想装饰部署在 AWS Lambda 上的 Quarkus RESTEasy Reactive 应用程序中的所有 HTTP 请求处理。

Quarkus Amazon Lambda HTTP 扩展可帮助用户通过 AWS API Gateway 集成在 AWS Lambda 上提供 RESTEasy Reactive 路由。 RESTEasy Reactive 允许用户使用标准的 ContainerResponseFilter 来装饰请求处理。但是,在资源抛出异常的情况下,不会调用响应过滤器。在我的用例中,我需要知道请求何时完成,即使它完成时出现错误。

如果在 servlet 容器上部署 RESTEasy Reactive,则可以使用 servlet 过滤器来装饰 RESTEasy 处理的所有请求。但是,在使用 Quarkus Amazon Lambda HTTP 扩展的部署中,如何装饰所有请求处理?

jax-rs quarkus
1个回答
0
投票
Jakarta Restful Webservices startard 定义了

filtersinterceptors 来处理修改传入请求或传出响应,以及 ExceptionMapper 接口来捕获异常并将异常映射到正确的 Response

 对象。

不幸的是,当抛出的异常未由

ContainerResponseFilter

 映射时,
WriterInterceptor
ExceptionMapper
都不会被调用

幸运的是,RestEasy Reactive 扩展提供了一个很好的拦截所有请求和响应的方法。

示例 REST 端点是:

@Path("/api") public class ExampleResource { @GET @Produces(MediaType.TEXT_PLAIN) public String hello() { return "Hello from RESTEasy Reactive"; } @GET @Path("/mapped") public String mapped(@NotBlank @QueryParam("param") String param) { return "Hello " + param + "!"; } @GET @Path("/unmapped") public String error(@QueryParam("param") String param) { if (null == param) { throw new IllegalArgumentException("Param problem"); } return "Hello " + param + "!"; } @DELETE public void noContent() { System.out.println("Got request"); } }

hello

方法仅返回带有静态响应正文的 200-OK 响应。
第二种方法称为
mapped
 接受查询参数。该参数由 Hibernate Validator 进行验证。无效的输入(空白或缺少参数)将引发由 
ResteasyReactiveViolationExceptionMapper 映射的异常
unmapped
 方法会抛出 
IllegalArgumentExpceiton
,但没有内置的 
ExceptionMapper
 来处理该问题。
最后说一个特殊情况。
noContent
方法将返回204-No Content,因此没有任何响应正文。

还有另外两个提供商:

@Provider public class SampleResponseFilter implements ContainerResponseFilter { @Override public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException { responseContext.getHeaders().add("X-ResponseFilter", "accepted"); } }

@Provider public class SampleWriterInterceptor implements WriterInterceptor { @Override public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException { context.getHeaders().add("X-Interceptor", "intercepted"); context.proceed(); } }
调用 hello(

/api

 端点)两个提供者都被调用

spinner@bistromath:~$ curl -v http://localhost:8080/api * Trying 127.0.0.1:8080... * Connected to localhost (127.0.0.1) port 8080 (#0) > GET /api HTTP/1.1 > Host: localhost:8080 > User-Agent: curl/7.81.0 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < Content-Type: text/plain;charset=UTF-8 < X-Interceptor: intercepted < X-ResponseFilter: accepted < content-length: 28 < * Connection #0 to host localhost left intact
调用 

/mapped

 端点:两个提供程序都被调用,因为前面提到的 
ExceptionMapper
 捕获了该异常并映射到 
Response
 对象。

spinner@bistromath:~$ curl -v http://localhost:8080/api/mapped * Trying 127.0.0.1:8080... * Connected to localhost (127.0.0.1) port 8080 (#0) > GET /api/mapped HTTP/1.1 > Host: localhost:8080 > User-Agent: curl/7.81.0 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 400 Bad Request < Content-Type: text/plain;charset=UTF-8 < validation-exception: true < X-Interceptor: intercepted < X-ResponseFilter: accepted < content-length: 131 < * Connection #0 to host localhost left intact
调用 

/unmapped

 没有调用任何已注册的提供程序。

spinner@bistromath:~$ curl -v http://localhost:8080/api/unmapped * Trying 127.0.0.1:8080... * Connected to localhost (127.0.0.1) port 8080 (#0) > GET /api/unmapped HTTP/1.1 > Host: localhost:8080 > User-Agent: curl/7.81.0 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 500 Internal Server Error < content-type: application/json; charset=utf-8 < content-length: 1337 < response body omitted for brevity
仅使用 

/api

 调用 
DELETE
 HTTP 方法 
SampleResponseFilter
,因为没有提供响应正文。

spinner@bistromath:~$ curl -v -X DELETE http://localhost:8080/api/silent * Trying 127.0.0.1:8080... * Connected to localhost (127.0.0.1) port 8080 (#0) > DELETE /api/silent HTTP/1.1 > Host: localhost:8080 > User-Agent: curl/7.81.0 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 204 No Content < X-ResponseFilter: accepted < * Connection #0 to host localhost left intact
Resteasy Reactive 允许注册自定义拦截器。这些拦截器将在每个请求和响应时被调用。

拦截器示例是:

import io.quarkus.vertx.http.runtime.filters.Filters; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.event.Observes; @ApplicationScoped public class SampleRouteFilter { void responseFilter(@Observes Filters filters) { filters.register(rc -> { rc.response().putHeader("X-RouteFilter", "filtered"); rc.next(); }, 1000); } }
从现在开始,每个响应都将包含 

X-RouteFilter

 标头键,无论该响应是否成功处理,是否由某个休息端点处理(例如,未找到或不允许方法)。

例如:

spinner@bistromath:~$ curl -v http://localhost:8080/api/unmapped * Trying 127.0.0.1:8080... * Connected to localhost (127.0.0.1) port 8080 (#0) > GET /api/unmapped HTTP/1.1 > Host: localhost:8080 > User-Agent: curl/7.81.0 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 500 Internal Server Error < X-RouteFilter: filtered < content-type: application/json; charset=utf-8 < content-length: 1337 <
或:

spinner@bistromath:~$ curl -v -X DELETE http://localhost:8080/api/unmapped * Trying 127.0.0.1:8080... * Connected to localhost (127.0.0.1) port 8080 (#0) > DELETE /api/unmapped HTTP/1.1 > Host: localhost:8080 > User-Agent: curl/7.81.0 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 405 Method Not Allowed < X-RouteFilter: filtered < X-ResponseFilter: accepted < content-length: 0 < * Connection #0 to host localhost left intact

注意:反应式过滤器注册到所有请求和响应。注册为/q/dev-ui

/q/health
等。所以在修改任何内容之前请小心。

© www.soinside.com 2019 - 2024. All rights reserved.