-
Notifications
You must be signed in to change notification settings - Fork 9.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IllegalArgumentException: Unexpected char ... in header value: ... at com.squareup.okhttp.Headers$Builder.checkNameAndValue (Headers.java:295) #2016
Comments
Any chance you can get the 3rd party library to fix? It's difficult to fix this in OkHttp because the request header contains invalid data. |
No problem, I can ask library developers try/catch that. Just wanted you to be aware about the issue. Imagine some other developer. His project works fine. He adds
After that his project starts crashing. He can't add try/catch becasue it happens in some 3rd party library. He can't fix the wrong header becasue it's in some 3rd party library. He's not hapy with "your header is incorrect" answer because the same header worked just fine for a long time with HttpUrlConnection. Probably not a big deal, I'm not sure. Just wanted issue to be created, may be helpful in further development :-) Thank you! |
Yeah, agreed. We decided to make it more strict than it was before on the expectation that most people weren't doing this deliberately. |
When someone passes you a Java However, the HTTP specification allows more than just ASCII (roughly, any octet except control characters). What happens when the response contains a header with non-ASCII? Do you just get rid of the non-ASCII parts? It might be worth having a |
I had that issue a few minutes ago. I used Android and the Base64 class with Base64.DEFAULT. When I change it to Base64.URL_SAFE, its working. Problem is, the server Patrick https://www.streetlife.com.mx
|
@pbertsch: What encoding does the server say you should use? Is there public documentation for the server you're sending requests to? (Aside: OkHttp should be fine with both DEFAULT and URL_SAFE -- both use only printable ASCII characters.) |
I used only NO_WRAP and it seems to work at the moment. I will try to write Patrick https://www.streetlife.com.mx
|
Ah, that's probably it. Newlines aren't allowed as header values. |
Hi, this restriction about just ASCII chars is very strange, we support chinese users etc... So almost all of our request fail when we try to send some chinese value using the header. This works fine in the HttpRequest apache. Why this restriction? |
@gudomau This restriction comes from official HTTP spec. |
Non-ASCII characters are allowed according to both the original and updated HTTP 1.1 specs. The updated spec recommends against using non-ASCII characters for newly-defined headers, but clearly they're allowed:
Because of the way UTF-8 is encoded, all codepoints above 127 are composed of bytes whose values are 128 or greater, which means they should pass through untouched. The only characters you have to be careful with are ASCII control characters and, in certain situations, spaces, quotes, and backslashes. |
How can I do that since all headers are validated by the checkNameAndValue ? |
The HTTP Spec actually uses the word SHOULD, so isn't this restriction in the http client too harsh? |
This relaxes some validation logic newly introduced in the version of OkHttp used in N. This change leaves the character code validation stricter than it was in M by still preventing control codes like \n, \r, backspace and delete. It does allow developers to pass Java characters > 7F to addRequestProperty() and also receive headers from servers which contain characters > 7F. Android's HttpURLConnection does not follow the HTTP spec as it encodes request header values and interprets response headers as UTF-8 and not ISO-8859-1. If a server is expecting or sending ISO-8859-1 encoded characters >7F in headers then these will still be corrupted or misinterpreted by Android. However, this has been the behavior since L and is not changed here. The OkHttp change which caused characters >7F to generate an IllegalArgumentException and partially reverted here: square/okhttp#1785 See also: square/okhttp#1998 square/okhttp#2016 for recent upstream bugs. Bug: 28867041 Bug: https://code.google.com/p/android/issues/detail?id=210205 (cherry picked from commit 75687ca5ae54f417afb4c02ba04767da6786d829) Change-Id: Ib640b58addff4c0c4eac589c77eb74a6bd6b3ec2
This reapplies AOSP commit 3c28a13 There is a chance that we may want to revert this change in future. Previous commit message: This relaxes some validation logic newly introduced in the version of OkHttp used in N. This change leaves the character code validation stricter than it was in M by still preventing control codes like \n, \r, backspace and delete. It does allow developers to pass Java characters > 7F to addRequestProperty() and also receive headers from servers which contain characters > 7F. Android's HttpURLConnection does not follow the HTTP spec as it encodes request header values and interprets response headers as UTF-8 and not ISO-8859-1. If a server is expecting or sending ISO-8859-1 encoded characters >7F in headers then these will still be corrupted or misinterpreted by Android. However, this has been the behavior since L and is not changed here. The OkHttp change which caused characters >7F to generate an IllegalArgumentException and partially reverted here: square/okhttp#1785 See also: square/okhttp#1998 square/okhttp#2016 for recent upstream bugs. Bug: 28867041 Bug: https://code.google.com/p/android/issues/detail?id=210205 (cherry picked from commit 75687ca5ae54f417afb4c02ba04767da6786d829) Change-Id: Id683ec13142f1d7d8792143066f1dd2e5f62cf86
This relaxes some validation logic newly introduced in the version of OkHttp used in N. This change leaves the character code validation stricter than it was in M by still preventing control codes like \n, \r, backspace and delete. It does allow developers to pass Java characters > 7F to addRequestProperty() and also receive headers from servers which contain characters > 7F. Android's HttpURLConnection does not follow the HTTP spec as it encodes request header values and interprets response headers as UTF-8 and not ISO-8859-1. If a server is expecting or sending ISO-8859-1 encoded characters >7F in headers then these will still be corrupted or misinterpreted by Android. However, this has been the behavior since L and is not changed here. The OkHttp change which caused characters >7F to generate an IllegalArgumentException and partially reverted here: square/okhttp#1785 See also: square/okhttp#1998 square/okhttp#2016 for recent upstream bugs. Bug: 28867041 Bug: https://code.google.com/p/android/issues/detail?id=210205 Change-Id: Ibdf14d819411a12fcc78d012bfca97db048b7e6e
so you're saying that "ç" and "é á ó" are "invalid data in headers"? Sorry but I respectfully disagree, the RFC does not say that, is the client being too strict. In my scenario, what's happening is that I use pagination with the Link header, but when my users are querying my API with special chars eg "ç ã é" this error is being thrown =| |
Alright, I can see the issue is fixed in new releases as mentioned #1998 sorry for my comment in an outdated thread. |
Whatever I use whether android.util.Base64.DEFAULT or URL_SAFE, as flag for Base64.encodeToString(...), it throws IllegalArgumentException. byte[] sigBytes = hmac.doFinal(reqStr.getBytes());
String sig = Base64.encodeToString(sigBytes, Base64.URL_SAFE);
...
Request.Builder builder = request.newBuilder()
.header("x-guoer-ts", signature.ts)
.header("x-guoer-nonce", signature.nonce)
.header("x-guoer-sig", signature.sig);
java.lang.IllegalArgumentException: Unexpected char 0x0a at 44 in x-guoer-sig value: IkObQzVpEFRv06bEwc5-CnSUO4rqYX_9Gdqs4qEJ_vI=
at okhttp3.Headers$Builder.checkNameAndValue(Headers.java:320)
at okhttp3.Headers$Builder.set(Headers.java:300)
at okhttp3.Request$Builder.header(Request.java:164) |
I regret that I used base64 which is always a trouble. I should use hex for it is stable and deterministic ascii. the code is running in production in iOS, it is hard to change now. |
Character For OkHttp: it might be good to quote strings in error messages so the mistake is more clear. Java string literal quoting or JSON quoting seem reasonable. |
Also consider using ByteString.base64() which might be a bit easier. |
Hi, just switched from Volley and this is the only issue we found, we understand what the standard suggests, however we have cookies we need to send in the header that contain Russian characters. Is there a way we can bypass the checkNameAndValue method? |
@kriskast: What value are you passing to OkHttp and what error are you seeing, exactly? |
Caused by: java.lang.IllegalArgumentException: Unexpected char 0x416 at 9 in User-Agent value: M.R.User=Ж
This is only a small extract of it as the cookie string is longer and has more Russian characters. |
Thats not valid HTTP. You might need to base64 encode it client-side and decode it server-side. ByteString from Okio can help with that. |
Thanks for your response, to Clarify
What do you mean by not valid HTTP? |
What happens when you use this cookie in a browser like Chrome or Safari? |
Also – make sure you're using the latest OkHttp. We recently fixed things to be consistent with major web browsers. |
Just to be clear, HTTP is a byte-oriented protocol so I'm assuming you want "Ж" to be encoded as UTF-8, which would be a two-byte sequence: 0xd0, 0x96. Loophole: use |
@swankjesse: Excluding control characters, UTF-8-encoded text is valid (in some sense) as an HTTP header value. See: #2016 (comment) |
Just checked on Chrome, looks like |
Correction, if I send @cakoose 's method is the best I found so far of using Thanks everyone |
@pbertsch good job |
|
Hi, I am trying to send "tête-à-tête.pdf" in my header and I am getting the same exception. But, I am able to send the same header from either Postman or using HttpsURLConnection. So, I don't understand why this restriction in okhttp when HTTP protocol supports this. |
Thanks! This works. I am suprised why was this not mentioned in this thread before. |
@rohitkum28 If you ask and self answer on stackoverflow, I'll bump up both. 25 points right there :) |
I did ask the question on StackOverflow and now that I know the answer I added it on Stackoverflow. |
thats because it wasn't possible at the time with the current version |
is this method is renamed as addLenient() now? |
I get crash reports like that:
Seems to happen due to non-ASCII chars in header value.
Similar to #1998. But #1998 is about response header and my smacktrace is about request header.
Thank you!
The text was updated successfully, but these errors were encountered: