【问题标题】:No form params in rest resource for form urlencoded when using Content, but application/json works?使用 Content 时,表单 urlencoded 的 rest 资源中没有表单参数,但 application/json 有效吗?
【发布时间】:2015-09-03 04:46:51
【问题描述】:

我有一个 REST 端点 @POST,当 Content-Type 为 application/x-www-form-urlencoded 时,表单参数为空。在链的前面有一个ContainerRequestFilter(底部的代码),它接受请求,将流更改为BufferedInputStream,然后记录请求。如果我删除此日志记录代码,则端点具有正确的表单参数。否则,它们为空,我不知道为什么。

现在,如果我使用 application/json,无论记录器是启用还是禁用,我的端点都有正确的参数。

我需要 application/x-www-form-urlencoded 因为 REST 端点需要重定向,并且如果请求不是标准的(预检)浏览器会阻止重定向

REST 端点不工作(OAuthRequest 有空成员)

@Stateless
@Path("v1/oauth2")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON)
public class OAuthTokenResource {

@POST
public Response getToken(@Form OAuthRequest oauthRequest) {
    ...
}

OAuthRequest

public class OAuthRequest {

    @FormParam(OAuthParam.CLIENT_ID)
    @JsonProperty(OAuthParam.CLIENT_ID)
    private String clientId;

    @URL
    @FormParam(OAuthParam.REDIRECT_URI)
    @JsonProperty(OAuthParam.REDIRECT_URI)
    private String redirectUri;

    @FormParam(OAuthParam.USERNAME)
    private String username;

    @FormParam(OAuthParam.PASSWORD)
    private String password;
    ...
}

日志过滤器

@Override
public void filter(final ContainerRequestContext context) throws IOException {
    ...
    if (logEntity && context.hasEntity()) {
        context.setEntityStream(logInboundEntity(builder, context.getEntityStream(), context.getMediaType()));
    }

    logger.debug(builder.toString());
}

private InputStream logInboundEntity(final StringBuilder builder, InputStream stream, MediaType mediaType) throws IOException {
    if (!stream.markSupported()) {
        stream = new BufferedInputStream(stream);
    }

    stream.mark(maxEntitySize + 1);
    final byte[] entity = new byte[maxEntitySize + 1];
    final int entitySize = stream.read(entity);

    if ( entitySize > 0 ) {
        String body = new String(entity, 0, Math.min(entitySize, maxEntitySize), StandardCharsets.UTF_8);
        builder.append("\nBody: ");
        builder.append(body);
    }

    if (entitySize > maxEntitySize) {
        builder.append(MORE_INDICATOR);
    }

    stream.reset();

    return stream;
}

【问题讨论】:

    标签: java rest content-type


    【解决方案1】:

    好吧,如果在过滤器链期间读取 InputStream,我仍然不确定为什么 @Form 和 @FormParam 不起作用。

    但是,我发现了一种解决方法,如下所示。

    @POST
    public Response getToken(MultivaluedMap<String, String> formParams) {
        ...
    }
    

    这提供了与 application/json 期间相同的行为,因为参数已经设置,即使 InputStream 已被使用。

    但出于安全原因,我们最终还是在过滤器中禁用了请求正文的日志记录。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-27
      • 2021-02-01
      • 2011-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-04
      相关资源
      最近更新 更多