19

次のコードを検討してください。

    OkHttpClient client = new OkHttpClient();

    MediaType mediaType = MediaType.parse("text/plain; charset=utf-8"); // [A]
    RequestBody body = RequestBody.create(mediaType, media);
    String[] aclHeader = "x-goog-acl:public-read".split(":");

    Request request = new Request.Builder()
            .addHeader("Content-Type", "text/plain") // [B]
            .addHeader(aclHeader[0], aclHeader[1])
            .url(url)
            .put(body)
            .build();

    Response response = client.newCall(request).execute();

以前に署名された URL を使用して、クライアントから GCS にアクセスしています。

問題: [B] では宣言されていませんが、okhttp は本文 [A] で宣言された文字セットを URL にも (少なくとも text/plain では) 追加しているようです。これは私の署名付き URL を台無しにし、GCS は 403 Forbidden を返します。

  • [A] から文字セットを削除しても、まだ追加されています。
  • 署名する前に署名付き URL に文字セットを追加すると、それは機能し、GCS は 200 OK を返します。

しかし、これはあるべき姿ではありません。少なくとも署名付き URL を使用する場合は、宣言どおりに正確にサーバーに送信する必要があります。

Apache http クライアントを使用してみました (okhttpclient は既にインストールの一部であるため、本番環境では使用したくありません)。そのクライアントはこの動作を公開しません。

        String[] aclHeader = "x-goog-acl:public-read".split(":");

        StatusLine statusLine = Request

                .Put(url)
                .addHeader("Content-Type", "text/plain")
                .addHeader(aclHeader[0], aclHeader[1])
                .bodyByteArray(media)

                .execute().returnResponse().getStatusLine();

Content-Type に追加するか、本文内で Content-Type を冗長に転送するという、okhttp の動作を抑制する方法はありますか?

4

2 に答える 2

27

私は解決策を見つけました:

次の行が原因です。

RequestBody body = RequestBody.create(mediaType, media);

create には、メディアの 3 つの署名があります。

  • バイト[]
  • ファイル

String を渡すと、指定された mediaType は無視され、charset が追加されます。image/jpegの場合でも送信します

画像/jpeg; 文字セット=utf-8

サーバーに。

byte[] または File を使用すると、その動作が抑制されます。

これがお役に立てば幸いです。

[愚かな私-簡単にするために、テスト中に文字列を指定しました。ボディは気にしませんでした;-( ]

于 2014-08-29T02:14:27.377 に答える