15

次のコードを使用して Content-Length ヘッダーを設定する必要がある Web サービスに投稿しようとしています。

// EDIT: added apache connector code
ClientConfig clientConfig = new ClientConfig();
ApacheConnector apache = new ApacheConnector(clientConfig);

// setup client to log requests and responses and their entities
client.register(new LoggingFilter(Logger.getLogger("com.example.app"), true));

Part part = new Part("123");
WebTarget target = client.target("https://api.thing.com/v1.0/thing/{thingId}");
Response jsonResponse = target.resolveTemplate("thingId", "abcdefg")
                .request(MediaType.APPLICATION_JSON)
                .header(HttpHeaders.AUTHORIZATION, "anauthcodehere")
                .post(Entity.json(part));

リリース ノートhttps://java.net/jira/browse/JERSEY-1617および Jersey 2.0 ドキュメントhttps://jersey.java.net/documentation/latest/message-body-workers.htmlから、Content-長さは自動設定されます。しかし、リクエストに Content-Length が存在しないことを示す 411 レスポンス コードがサーバーから返されます。

Content-Length ヘッダー セットを取得する最良の方法を知っている人はいますか?

リクエストで Content-Length ヘッダーが生成されないことをロガーを設定することで確認しました。

ありがとう。

4

5 に答える 5

5

Jersey Client 2.2 と Netcat で簡単なテストを実行したところ、LoggingFilter が報告していなくても、Jersey が Content-Length ヘッダーを送信していることがわかりました。

このテストを行うために、まず 1 つのシェルで netcat を実行しました。

nc -l 8090

次に、別のシェルで次のジャージー コードを実行しました。

Response response = ClientBuilder.newClient()
    .register(new LoggingFilter(Logger.getLogger("com.example.app"), true))
    .target("http://localhost:8090/test")
    .request()
    .post(Entity.json(IOUtils.toInputStream("{key:\"value\"}")));

このコードを実行すると、次の行がログに記録されます。

INFO: 1 * LoggingFilter - Request received on thread main
1 > POST http://localhost:8090/test
1 > Content-Type: application/json
{key:"value"}

ただし、netcat はメッセージ内でさらにいくつかのヘッダーを報告します。

POST /test HTTP/1.1
Content-Type: application/json
User-Agent: Jersey/2.0 (HttpUrlConnection 1.7.0_17)
Host: localhost:8090
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Content-Length: 13

{key:"value"}

Java6 と Java7 を搭載した OSX でこのテストを実行しましたが、結果は同じでした。また、Jersey 2.0 でテストを実行したところ、同様の結果が得られました。

于 2013-08-26T00:57:12.793 に答える
4

私は、Jersey 2.25.1 をsetChunkedEncodingEnabled(false)使用して、Jersey Client 構成での設定からなるより単純なソリューションをテストしました。チャンク エンコーディングを使用する代わりに、エンティティ全体がメモリ内でシリアル化され、Content-Length が要求に設定されます。

参考までに、私が使用した構成の例を次に示します。

private Client createJerseyClient(Environment environment) {
    Logger logger = Logger.getLogger(getClass().getName());
    JerseyClientConfiguration clientConfig = new JerseyClientConfiguration();
    clientConfig.setProxyConfiguration(new ProxyConfiguration("localhost", 3333));
    clientConfig.setGzipEnabled(false);
    clientConfig.setGzipEnabledForRequests(false);
    clientConfig.setChunkedEncodingEnabled(false);
    return new JerseyClientBuilder(environment)
            .using(clientConfig)
            .build("RestClient")
            .register(new LoggingFeature(logger, Level.INFO, null, null));
}

mitmproxyを使用してリクエスト ヘッダーとContent-Lengthヘッダーが正しく設定されていることを確認しました。

于 2017-07-07T14:07:50.233 に答える
3

これは、Jersey 2.5 ( https://java.net/jira/browse/JERSEY-2224 ) でサポートされています。https://jersey.java.net/apidocs/latest/jersey/org/glassfish/jersey/client/RequestEntityProcessing.html#BUFFEREDを使用してコンテンツをストリーミングできます。ApacheConnector を使用したチャンク コンテンツとバッファリング コンテンツの両方を示す簡単な例をまとめました。このプロジェクトをチェックしてください: https://github.com/aruld/sof-18157218

public class EntityStreamingTest extends JerseyTest {

  private static final Logger LOGGER = Logger.getLogger(EntityStreamingTest.class.getName());

  @Path("/test")
  public static class HttpMethodResource {
    @POST
    @Path("chunked")
    public String postChunked(@HeaderParam("Transfer-Encoding") String transferEncoding, String entity) {
      assertEquals("POST", entity);
      assertEquals("chunked", transferEncoding);
      return entity;
    }

    @POST
    public String postBuffering(@HeaderParam("Content-Length") String contentLength, String entity) {
      assertEquals("POST", entity);
      assertEquals(entity.length(), Integer.parseInt(contentLength));
      return entity;
    }
  }

  @Override
  protected Application configure() {
    ResourceConfig config = new ResourceConfig(HttpMethodResource.class);
    config.register(new LoggingFilter(LOGGER, true));
    return config;
  }

  @Override
  protected void configureClient(ClientConfig config) {
    config.connectorProvider(new ApacheConnectorProvider());
  }

  @Test
  public void testPostChunked() {
    Response response = target().path("test/chunked").request().post(Entity.text("POST"));

    assertEquals(200, response.getStatus());
    assertTrue(response.hasEntity());
  }

  @Test
  public void testPostBuffering() {
    ClientConfig cc = new ClientConfig();
    cc.property(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.BUFFERED);
    cc.connectorProvider(new ApacheConnectorProvider());
    JerseyClient client = JerseyClientBuilder.createClient(cc);
    WebTarget target = client.target(getBaseUri());
    Response response = target.path("test").request().post(Entity.text("POST"));

    assertEquals(200, response.getStatus());
    assertTrue(response.hasEntity());
  }
}
于 2014-02-09T00:56:18.110 に答える