2012-12-04 7 views
6

Webサービスを構築するためにDropwizard/Jerseyを使用しています。リソースにはパスがあり、メソッドにはサブパスがあります。作成されたレスポンスを返すとき(201)、取得しているメソッドのパスが、与えられた場所の先頭に追加されます。私が知っているように思ったような場所でステータスOKを返すと、すべてがうまくなり、ロケーションを返されます。Javaxレスポンスは、Locationヘッダパスをステータス作成時に追加します。

メソッドの場所のサブパスではない場所を返すにはどうすればよいですか?以下の例では

: "のhttp:// localhostの/ fooの/バー" を取得(ステータスを作成したが)の場所で応答は "http:// localhostの/ fooの/バー/ 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(); 
    } 
} 

答えて

4

GlassFish(JavaEE6)で私に起こりました。 私はそれはバグだと思うが、私は、実際のURIへの変換コードを掘ることに成功したことがない....

私も回避策を見つけた:誰かが疑問を抱いてここでつまずくケースで

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

ありがとう、私はそれを試してみます。現時点での回避策は、JSONにシリアル化されたオブジェクト内のURLとともにステータス200を返すことです。 –

7

をこの;私はJerseyのコードを掘り出して、なぜこのようなことが起こるかを確認しました。これはあなたの問題を説明する必要があります&カルロの回避策。言い換えれば

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

com.sun.jersey.spi.container.ContainerResponseは、この宝石が含まれているいくつかの理由のために、誰かが応答ならば、違った場所ヘッダーを治療するための良いアイデアと判断しましたステータスコードは201です。Carloが気づいたように、絶対パスを使用するとこの問題は回避されます。

+0

うわー!探偵作品のおかげで、ありがとうございました。あなたの "WHY"コメントは元のソースですか? (すなわち、ジャージーの開発者でさえこれが奇妙だと思うのですか?) –

+1

私はWHYを強調しました。私はそれについてもっと明確にすべきでした:) – 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内部に、以下の方法が呼び出されるアプリケーションがロケーションヘッダの(http:又はftp:ようなスキーマで始まるURI)絶対URIを設定しない限り

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

としては、先に述べましたJerseyはリクエストのベースURIを自動的に付加します。

Jerseyではこの動作を制御または無効にすることはできません。

関連する問題