5

次の例が、リクエストの「Content-Encoding」の HTTP ヘッダーを飲み込むのはなぜですか。カスタム エンコーディング形式をデコードする必要があるアプリケーションを作成しています。ただし、リクエストから「Content-Encoding」ヘッダーを取得することはできません。実際のリソースにも ReaderInterceptor にもありません。応答では、このエンコーディング ヘッダーは飲み込まれません。

この動作は、次の (実行可能な) 例で簡単に確認できます。

public class Demo extends JerseyTest {
  @Override
  protected Application configure() {
    enable(TestProperties.DUMP_ENTITY);
    enable(TestProperties.LOG_TRAFFIC);
    return new ResourceConfig(MyResource.class, MyInterceptor.class);
  }

  public static final String PATH = "path";
  public static final String ENCODING = "my-encoding";
  public static final String CUSTOM_HEADER = "X-Content-Encoding";
  public static final String QUESTION = "question", ANSWER = "answer";

  @Path(PATH)
  public static class MyResource {
    @POST
    public Response handle(String value, @Context HttpHeaders httpHeaders) {
      assertEquals(ENCODING, httpHeaders.getHeaderString(CUSTOM_HEADER));
      // Here, the "Content-Encoding" header mysteriously disappeared.
      assertEquals(ENCODING, httpHeaders.getHeaderString(HttpHeaders.CONTENT_ENCODING));
      return Response
          .ok(ANSWER)
          .header(CUSTOM_HEADER, ENCODING)
          .header(HttpHeaders.CONTENT_ENCODING, ENCODING)
          .build();
    }
  }

  public static class MyInterceptor implements ReaderInterceptor, WriterInterceptor {
    @Override
    public Object aroundReadFrom(ReaderInterceptorContext context) 
        throws IOException, WebApplicationException {
      assertEquals(ENCODING, context.getHeaders().getFirst(CUSTOM_HEADER));
      // Here, the "Content-Encoding" header mysteriously disappeared.
      assertEquals(ENCODING, context.getHeaders().getFirst(HttpHeaders.CONTENT_ENCODING));
      return context.proceed();
    }

    @Override
    public void aroundWriteTo(WriterInterceptorContext context) 
        throws IOException, WebApplicationException {
      assertEquals(ENCODING, context.getHeaders().getFirst(CUSTOM_HEADER));
      // Here, the "Content-Encoding" header can be found.
      assertEquals(ENCODING, context.getHeaders().getFirst(HttpHeaders.CONTENT_ENCODING));
      context.proceed();
    }
  }

  @Test
  public void test() throws Exception {
    Response response = target(PATH)
        .request()
        .header(CUSTOM_HEADER, ENCODING)
        .header(HttpHeaders.CONTENT_ENCODING, ENCODING)
        .post(Entity.text(QUESTION));
    assertEquals(200, response.getStatus());
    assertEquals(ENCODING, response.getHeaders().getFirst(CUSTOM_HEADER));
    // Here, the "Content-Encoding" header can be found.
    assertEquals(ENCODING, response.getHeaders().getFirst(HttpHeaders.CONTENT_ENCODING));
  }
}

Jersey がコンテンツのエンコーディングを修正しようとするとき、カーテンの後ろで何か魔法が起こっているのでしょうか? (実際には、ネットワーク内の別のサーバー上の別のアプリケーションにクエリを実行することで解決する必要があるクローズドソースのエンコーディングであるため、できないこと。)リクエストダンプで「Content-Encoding」ヘッダーを見つけることさえできないため、 Jersey がヘッダーをまったく送信していないと思われます。

もちろん、「X-Content-Encoding」ヘッダーを使用することもできます。これは、例で示したように機能します。しかし、この解決策はばかげています。すでにさまざまな定数プールを検索しましCommonPropertiesServerPropertiesClientProperties、構成オプションが見つかりませんでした。

4

1 に答える 1

8

表示される問題は、Content-Encoding ヘッダーを効果的に上書きしているためです。

.post(Entity.text(QUESTION));

電話。このEntity.text(...)メソッドは、コンテンツ データVariantフィールドが次のように設定されたエンティティを生成します。

media type = "text/plain";
content language = null;
content encoding = null;

これらnullのコンテンツ エンコーディングと言語の値により、以前に設定されたヘッダーが消去されContent-EncodingますContent-Language。これを修正するには、エンティティの一部としてコンテンツ エンコーディングを指定する必要があります。

    Response response = target(PATH)
            .request()
            .post(Entity.entity(QUESTION, 
                  new Variant(MediaType.TEXT_PLAIN_TYPE, (String) null, "my-encoding")));

(この動作は明らかではないため、多少混乱することに同意します。おそらく、Jersey を修正して、nullバリアント フィールド値が設定されている場合にヘッダーをオーバーライドしないようにする必要があります...)

于 2013-11-05T19:08:52.213 に答える