简体   繁体   English

如何使用 Apache Camel REST DSL (Servlet/Restlet) 设置 HTTP 状态代码原因

[英]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 默认ServletRestlet组件,我没有在响应中获得 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 状态代码中包含原因?

Without a custom core, I believe you can't:如果没有自定义核心,我相信你不能:

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 ,但它是不可访问的。


Answer:回答:

Without custom core,没有自定义核心, (I believe) (我相信) you can't!你不能!


... what isn't inappropriate, given that: ...考虑到以下情况,这不是不合适的:

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 状态行中的版本或原因短语的方法。

Need to know the meaning of a status code?需要知道状态码的含义吗?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM