2012-12-04 69 views
6

我們使用Dropwizard/Jersey構建Web服務。資源有一個路徑,該方法有一個子路徑。當返回創建的響應(201)時,我們獲得的方法的路徑被預先添加到我們提供的位置。當返回狀態確定與一個位置(我知道設法),一切都很好,位置返回就像我們提供它。Javax響應在設置「狀態」創建位置標題路徑時預先設置方法路徑

我們如何返回一個不是我們方法位置的子路徑的位置?

在下面的例子: A到的 「http://本地主機/富/欄」(創建狀態)與位置響應的 「http://本地主機/富/酒吧/維布勒」(注意/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(); 
    } 
} 

回答

4

發生在GlassFish(JavaEE6)上的我。 我認爲這是一個錯誤,但我從來沒有設法挖代碼實際URI轉換....

我發現雖然解決方法:

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

謝謝,我會嘗試。我們目前的解決方法是將狀態200與對象中的URL一起返回,該對象被序列化爲JSON。 –

7

,以防有人絆倒在這裏想知道這個;我深入瞭解澤西島的代碼,看看爲什麼會發生這種情況。這應該解釋您的問題& Carlo的解決方法。

com.sun.jersey.spi.container.ContainerResponse包含此寶石:

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注意到的,使用絕對路徑可以避免這個問題。

+0

哇!感謝偵探工作的好處 - 是你的「爲什麼」評論,還是原始來源? (即使澤西開發人員認爲這很奇怪嗎?) –

+1

我加了爲什麼要強調,我應該已經更清楚了:) – henriks

+0

難道是因爲規範(http://www.w3.org/Protocols /rfc2616/rfc2616-sec10.html#sec10.2.2)說:「由Location頭域給出的資源的最具體URI」.. – Jonas

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)); 
    } 

正如前面所說的,除非應用程序設置的絕對URI(一個URI,與像http:ftp:一個模式啓動)的位置標頭,Jersey會自動將它與請求的基本URI一起預先配置。

澤西島不允許控制或禁用此行爲是很奇怪的。