Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to suppress Charset being automatically added to Content-Type in okhttp

Consider the following code:

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

I am accessing GCS from a client, with a previously signed URL.

Problem: It seems okhttp adds the charset declared for the body [A] to the URL as well (at least for text/plain), even though it is not declared in [B]. This messes up my signed URL and GCS returns 403 Forbidden.

  • If I remove the charset from [A], it is still added.
  • If I add the charset to the signed URL before I sign it, it works and GCS returns 200 OK.

But this is not as it should be. At least when working with signed URLs, these must be sent to the server exactly as declared.

I tried using the Apache http client (which I don't want to use in production as okhttpclient is already part of my installation) and that client does not expose this behavior:

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

Is there a way to suppress the behavior in okhttp, that it adds to the Content-Type or transfers the Content-Type within the body redundantly?

like image 924
Oliver Hausler Avatar asked Aug 29 '14 01:08

Oliver Hausler


People also ask

How to remove charset in content Type?

Removing the Charset From a Content-Type Header Solution is simple - we can create StringContent with whatever encoding and then set charset to empty string. This removes the charset definiton from the request content-type header. My code started to work after this change.

What is MediaType parse?

static MediaType. parse(String string) Returns a media type for string , or null if string is not a well-formed media type. String.


1 Answers

I found the solution:

The following line is the culprit:

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

create has 3 signatures for media:

  • String
  • byte[]
  • File

When I pass a String, it disregards the supplied mediaType and adds the charset to it. Even for image/jpeg it would send

image/jpeg; charset=utf-8

to the server.

Using byte[] or File suppresses that behavior.

I hope this helps you!

[Stupid me - for simplicity I gave it a String during testing, as I didn't care about the body ;-( ]

like image 96
Oliver Hausler Avatar answered Sep 20 '22 09:09

Oliver Hausler