[英]How to set HTTP Status code reason with Apache Camel REST DSL (Servlet/Restlet)
I have a web application built using Spring Boot with Apache Camel and I'm implementing a REST interface.我有一个使用 Spring Boot 和 Apache Camel 构建的 Web 应用程序,并且我正在实现一个 REST 接口。 Currently, using either Camel default
Servlet
or Restlet
component, I'm not getting the HTTP Status code reason in the response.目前,使用 Camel 默认
Servlet
或Restlet
组件,我没有在响应中获得 HTTP 状态代码原因。
Here is an example response I'm getting while setting the HTTP Status code to 403:这是我在将 HTTP 状态代码设置为 403 时收到的示例响应:
< HTTP/1.1 403
< Date: Mon, 19 Feb 2018 10:01:21 GMT
< Server: Restlet-Framework/2.4.0
< Content-Type: application/json
< Content-Length: 75
How it should be:应该如何:
< HTTP/1.1 403 Forbidden
< Date: Mon, 19 Feb 2018 10:01:21 GMT
< Server: Restlet-Framework/2.4.0
< Content-Type: application/json
< Content-Length: 75
How can I configure Camel/Restlet/Servlet to include the reason on the HTTP Status code?如何配置 Camel/Restlet/Servlet 以在 HTTP 状态代码中包含原因?
My current configuration:我目前的配置:
Application.java应用程序.java
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
private static final Logger appLogger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
appLogger.info("--Application Started--");
}
@Bean
public ServletRegistrationBean servletRegistrationBean() {
SpringServerServlet serverServlet = new SpringServerServlet();
ServletRegistrationBean regBean = new ServletRegistrationBean(serverServlet, "/*");
Map<String,String> params = new HashMap<>();
params.put("org.restlet.component", "restletComponent");
regBean.setInitParameters(params);
return regBean;
}
@Bean
public Component restletComponent() {
return new Component();
}
@Bean
public RestletComponent restletComponentService() {
return new RestletComponent(restletComponent());
}
}
Route Configuration:路线配置:
@Component
public class RestRouteBuilder extends RouteBuilder {
private static final Logger appLogger = LoggerFactory.getLogger(RestRouteBuilder.class);
private Predicate isAuthorizedRequest = header(HttpHeaders.AUTHORIZATION).isNotNull();
@Override
public void configure() throws Exception {
restConfiguration().component("restlet")
.contextPath("/overlay")
.bindingMode(RestBindingMode.json)
.skipBindingOnErrorCode(false)
.dataFormatProperty("prettyPrint", "true");
rest("/")
.get()
.route()
.setHeader(Exchange.HTTP_RESPONSE_CODE, constant(403))
.setBody(constant("Forbidden"))
.endRest();
}
}
I also tried adding .setHeader(Exchange.HTTP_RESPONSE_TEXT, constant("Forbidden"))
but the result was the same.我也尝试添加
.setHeader(Exchange.HTTP_RESPONSE_TEXT, constant("Forbidden"))
但结果是一样的。
.setHeader(Exchange.HTTP_RESPONSE_CODE, constant(403))
.setHeader(Exchange.CONTENT_TYPE, constant("text/plain"))
.setBody(constant("Forbidden"))
How can I configure Camel/Restlet/Servlet to include the reason on the HTTP Status code?
如何配置 Camel/Restlet/Servlet 以在 HTTP 状态代码中包含原因?
The response is being sent at org.restlet.engine.adapter.ServerCall.sendResponse() , where the response head and body are written to the OutputStream :响应被发送到org.restlet.engine.adapter.ServerCall.sendResponse() ,其中响应头和正文被写入 OutputStream :
writeResponseHead(response); // <--
if (responseEntity != null) {
responseEntityStream = getResponseEntityStream();
writeResponseBody(responseEntity, responseEntityStream);
}
... and writeResponseHead(response) does nothing by default , check it : ...并且writeResponseHead(response)默认情况下什么都不做, 检查一下:
protected void writeResponseHead(Response response) throws IOException {
// Do nothing by default
}
Update: ... the HttpStatus(value, reasonPhrase) has the reasonPhrase , but isn't used to stringify :更新: ... HttpStatus(value, reasonPhrase)有reasonPhrase ,但不用于stringify :
HttpStatus(int value, String reasonPhrase) {
this.value = value;
this.reasonPhrase = reasonPhrase;
}
...
@Override
public String toString() {
return Integer.toString(this.value);
}
Update 2: ... the DefaultRestletBinding .更新 2: ... DefaultRestletBinding 。 populateRestletResponseFromExchange does the following:
populateRestletResponseFromExchange执行以下操作:
// get response code
Integer responseCode = out.getHeader(Exchange.HTTP_RESPONSE_CODE, Integer.class);
if (responseCode != null) {
response.setStatus(Status.valueOf(responseCode));
}
... it only uses the Status . ...它只使用Status 。 valueOf .
价值。
Although there is a Status.reasonPhrase , it isn't accessible.尽管有一个Status.reasonPhrase ,但它是不可访问的。
6.1.1 Status Code and Reason Phrase
6.1.1 状态码和原因短语
(...) The client is not required to examine or display the Reason-Phrase.
(...) 客户不需要检查或显示原因短语。
(...) The reason phrases (...) MAY be replaced by local equivalents without affecting the protocol.
(...) 原因短语 (...) 可以替换为本地等效项,而不影响协议。
3.1.2.
3.1.2。 Status Line
状态行
(...) A client SHOULD ignore the reason-phrase content.
(...) 客户端应该忽略原因短语内容。
8.1.2.4.
8.1.2.4。 Response Pseudo-Header Fields
响应伪标头字段
(...) HTTP/2 does not define a way to carry the version or reason phrase that is included in an HTTP/1.1 status line.
(...) HTTP/2 没有定义携带包含在 HTTP/1.1 状态行中的版本或原因短语的方法。
See the complete list of status codes maintained by IANA .请参阅IANA 维护的状态代码的完整列表。
TLDR - use .setHeader(Exchange.HTTP_RESPONSE_CODE, 403)
TLDR - 使用
.setHeader(Exchange.HTTP_RESPONSE_CODE, 403)
I found out that我发现
.setHeader(Exchange.HTTP_RESPONSE_CODE, constant(403))
does not work but .setHeader(Exchange.HTTP_RESPONSE_CODE, constant(403))
不起作用但
.setHeader(Exchange.HTTP_RESPONSE_CODE, 403)
DOES. .setHeader(Exchange.HTTP_RESPONSE_CODE, 403)
。
Mind the constant
keyword difference.注意
constant
的关键字差异。 You need to use constant
when setting values directly in the route, but eg in Processor you do not.直接在路由中设置值时需要使用
constant
,但例如在处理器中则不需要。 Therefore you can set response status code whenever exception occurs in code, not in the route builder config.因此,您可以在代码中发生异常时设置响应状态代码,而不是在路由构建器配置中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.