在Status Created上设置Location头路径时,Javax Response会预先设置方法路径

时间:2012-12-04 12:04:59

标签: java http jersey dropwizard

我们正在使用Dropwizard / Jersey来构建Web服务。资源具有路径,并且该方法具有子路径。当返回创建的响应(201)时,我们获得的方法的路径被添加到我们提供的位置之前。当一个位置(我知道设计)返回状态OK时,一切都很好,并且就像我们提供的那样返回位置。

我们如何返回不是我们方法位置的子路径的位置?

在下面的示例中: 获取“http:// localhost / foo / bar”(创建状态)以“http:// localhost / foo / bar / wibble”的位置响应(注意 / foo / bar

当到达“http:// localhost / foo / baz”(ok状态)时,响应位置为“http:// localhost / wibble”,这就是我们想要的。

import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import java.net.URI;

@Path("/foo")
public class FooResource {

    @POST
    @Path("/bar")
    public Response bar() {

        URI uriOfCreatedResource = URI.create("/wibble");
        return Response.created(uriOfCreatedResource).build();
    }

    @POST
    @Path("/baz")
    public Response baz() {

        URI uriOfCreatedResource = URI.create("/wibble");
        return Response.ok().location(uriOfCreatedResource).build();
    }
}

3 个答案:

答案 0 :(得分:7)

如果有人偶然发现这件事;我挖了泽西的代码,看看为什么会这样。这应该解释你的问题&卡罗的解决方法。

com.sun.jersey.spi.container.ContainerResponse包含此gem:

private void setHeaders(MultivaluedMap<String, Object> headers) {
    this.headers = headers;
    Object location = headers.getFirst(HttpHeaders.LOCATION);
    if (location != null) {
        if (location instanceof URI) {
            final URI locationUri = (URI)location;
            if (!locationUri.isAbsolute()) {
                final URI base = (statusType.getStatusCode() == Status.CREATED.getStatusCode())
                        ? request.getAbsolutePath() // WHY!?
                        : request.getBaseUri();
                location = UriBuilder.fromUri(base).
                        path(locationUri.getRawPath()).
                        replaceQuery(locationUri.getRawQuery()).
                        fragment(locationUri.getRawFragment()).
                        build();
            }
            headers.putSingle(HttpHeaders.LOCATION, location);
        }
    }
}

换句话说:出于某种原因,有人认为如果响应状态代码是201,则以不同方式处理位置标题是个好主意。像Carlo注意到的那样,使用绝对路径可以避免这个问题。

答案 1 :(得分:4)

在GlassFish(JavaEE6)上发生了我的事。 我认为这是一个错误,但我从未设法将代码挖掘到实际的URI转换....

我找到了一个解决方法:

public Response bar(@Context UriInfo info) {
   URI absoluteURI=info.getBaseUriBuilder().path("/wibble").build();
   return Response.created(absoluteURI).build();
}

答案 2 :(得分:0)

在Jersey 2.x中,相关代码被完全重写并移至另一个地方。在类org.glassfish.jersey.server.ServerRuntime内,在编写响应数据时调用以下方法:

   private static void ensureAbsolute(final URI location, final MultivaluedMap<String, Object> headers,
                                       final ContainerRequest request) {
        if (location == null || location.isAbsolute()) {
            return;
        }
        // according to RFC2616 (HTTP/1.1), this field can contain one single URI
        headers.putSingle(HttpHeaders.LOCATION, request.getBaseUri().resolve(location));
    }

如前所述,除非应用程序为Location标头设置绝对URI(以http:ftp:等模式开头的URI),否则Jersey会自动使用请求的基URI预先设置它。

很奇怪泽西岛不允许控制或禁用此行为。