web-dev-qa-db-ja.com

Content-Typeを含むGETリクエストとJAX-RS Jersey 2.2を含むAcceptヘッダー

私は私に交通情報を与えるオープンデータウェブサービスにアクセスしようとします。ドキュメントには、リクエストはGETである必要があり、_Accept: application/json_および_Content-Type: application/json_を含める必要があると記載されています。 _Content-Type_が必要な理由がわかりませんが、

_Accept:_ヘッダーだけでデータを取得しようとしましたが、常に_415 Unsupported Media Type_を取得しています。現在、私は現在この方法を試しています(しかし、本当に両方のヘッダーを正しく設定しているかどうかはわかりません):

_String entity = ClientBuilder.newClient().target(liveDataURI)
    .path(liveDataPath)
    .request(MediaType.APPLICATION_JSON)
    .accept(MediaType.APPLICATION_JSON)
    .get(String.class);
_

ご覧のとおり、私はJersey 2.2を使用していますが、まだ_415 Unsupported Media Type_を取得しています。

[〜#〜]編集[〜#〜]

だから私はそれを動作させましたが、なぜかわかりません。 accept(MediaType.APPLICATION_JSON)header("Content-type","application/json")は同じではありませんか?

_String responseEntity = ClientBuilder.newClient()
    .target(liveDataURI)
    .path(liveDataPath)
    .request(MediaType.APPLICATION_JSON)
    .header("Content-type", "application/json")
    .get(String.class);
_
14
Shady

Acceptヘッダーは、クライアントが何を望んでいるかをサーバーに伝えます。 _Content-Type_ヘッダーは、クライアントがリクエストで送信したものをサーバーに通知します。したがって、この2つは同じではありません

サーバーが_application/json_のみを受け入れる場合は、要求の内容を指定する要求を送信する必要があります。

_Content-Type: application/json
_

これが、編集したコードが機能する理由です。

編集

最初のコードでは WebTarget.request(MediaType... acceptedResponseTypes) を使用します。このメソッドのパラメーター

受け入れられる応答メディアタイプを定義します。

このメソッド呼び出しの結果で Innvocation.Builder.accept(MediaType... mediaTypes) を使用しています。ただし、accept()は新しいヘッダーを追加しません。最初のコードでは不要です。

リクエストのコンテンツタイプを指定することはありません。サーバーは_Content-Type_ヘッダーを想定しているため、_415_で応答します。

16
user1907906

accept(MediaType.APPLICATION_JSON)header("Content-type","application/json")は同じではありませんか?

いいえ、違います。
これは、それらがどのように関連しているかです。

_Client                     Server
(header)                   (class/method annotation)
====================================================
Accept          <--->      @Produces
Content-Type    <--->      @Consumes
_

サーバーは、クライアントから受信したものを本文で消費し(その形式は_Content-Type_で指定されます)、クライアントが受け入れるものを生成します(その形式はAcceptで指定されます)。

  • clientは次のヘッダーを送信します:
    • _Content-Type_ = _text/xml_(本文でXMLを送信します)
    • Accept = _application/json_(JSONを応答として受け取ることを期待しています)
  • serverは、対応するメソッドに少なくとも以下のアノテーションが必要です(アノテーションは、そのメソッドで明示的に言及されていない場合、クラスレベルから取得されます):
    • @Consumes(MediaType.TEXT_XML)(クライアントからXMLを取得します)
    • @Produces(MediaType.APPLICATION_JSON)(JSONをクライアントに送信します)

Obs

  1. サーバーはより柔軟になり、multiple可能formatsを取得/生成するように構成されます。

    例:@Consumes({ MediaType.APPLICATION_JSON, MediaType.TEXT_XML })アノテーションがある場合、クライアントはXMLを送信できますが、別のクライアントは同じメソッドにJSONを送信できます。

  2. MediaType値は単なるString定数です:

    _public final static String APPLICATION_JSON = "application/json";
    public final static String TEXT_XML = "text/xml";
    _
13

ContainerResponseFilterを使用して、デフォルトのAcceptヘッダーを入力リクエストで提供されていない場合に設定できます。

@Provider
public class EntityResponseFilter implements ContainerResponseFilter {

    private MediaType getExternalMediaType(){
        MediaType mediaType = new MediaType("application", "vnd.xxx.resource+json")
        return mediaType; 
    }

    @Override
    public void filter( ContainerRequestContext reqc , ContainerResponseContext resc ) throws IOException {
        MediaType mediaType = getExternalMediaType(); 
        List<MediaType> mediaTypes = reqc.getAcceptableMediaTypes();
        if( mediaTypes.contains(mediaType) ) {   
            resc.setEntity( resc.getEntity(), new Annotation[0], mediaType );
        }
        // ...
    }
}
2
vikas jain