http
http copied to clipboard
Remove charset from "Content-Type" header
Hello,
I need to post some data to a distant API. But it looks like the API wants Content-Type: application/json but I'm sending a Content-Type: application/json; charset=utf-8.
I forced the headers:
Map<String, String> headers = {
HttpHeaders.AUTHORIZATION: 'Bearer ${this._token}',
HttpHeaders.CONTENT_TYPE: 'application/json'
};
but keep sending with the charset. Is there a possibility to remove it from the Content Typeheader ?
Thanks
Looks like charset ("encoding") is always added on Content-Type in case it's not set: https://github.com/dart-lang/http/blob/master/lib/src/request.dart#L84-L92
For good measure I checked with the RFCs and it seems the "parameter" part of the Content-Type value is either mandatory or optional depending on the particular MIME type/subtype: https://tools.ietf.org/html/rfc2045#section-5
As far as I can tell the 'application/json' MIME type does explicitly not define a "charset" parameter: https://www.iana.org/assignments/media-types/application/json
Ultimately this points to the http package being buggy. I don't think it's valid to blindly add parameters to just any MIME type. In fact, while probably done with good intentions, silently adding anything should probably be avoided.
Work-around: Set the body first (this sets default headers), then set the headers.
I have the same problem, however the above solution did not work in my case.
For clarity, this is what worked for me: Request request = new Request('POST', Uri.parse(url)); request.body = body; request.headers['content-type'] = 'text/xml'; request.headers['accept'] = 'text/xml';
I encountered the same issue, but @jheyne workaround didn't work for me.
We should be able to write request.encoding = null.
Good afternoon,
I have the same problem.
The lib is automatically placing charset = utf-8 in the request header, so I'm having trouble consuming some REST WebServices, making it impossible to use it.
The issue is already open for one year.
Is there no solution to such a problem?
Thank you.
Cristian Regazzo
Has anyone solved this yet?
It seems to be more of a problem when there encoding more complex types such as
class MyClass { ClassOne class1; ClassTwo class2; }
I've tried jsonEncode, I've used the JSONSerializable package, setting the body before headers, just as @jheyne mentioned. I don't understand why the HttpClient encodes to UTF-8 by default. Either way, life is very difficult right now. I've even added UTF-8 encoding to my .NET server and still nothing :(
Marc
Has anybody found a solution to this yet? I'm running into the same problem with my REST endpoint refusing to accept my requests because it doesn't expect the charset property to be set.
For now I have a local solution by copying the Package locally and modifying lib/src/request.dart to remove the lines that add charset if it's not there: (based on @cskau-g 's comment earlier)
request.dart
91 set body(String value) {
92 bodyBytes = encoding.encode(value);
93 var contentType = _contentType;
94 if (contentType == null) {
95 _contentType = MediaType('text', 'plain', {'charset': encoding.name});
- } else if (!contentType.parameters.containsKey('charset')) {
- _contentType = contentType.change(parameters: {'charset': encoding.name});
96 }
97 }
You can find that code excerpt at https://github.com/dart-lang/http/blob/master/lib/src/request.dart#L84-L92
@jefioliveira tried to made a pull request for a similar change but it was understandably denied because a lot of applications probably rely on the current auto-addition of charset. It's been six months since then.
Would it be possible to just add an additional optional parameter to the Request class that would tell it not to add charset?
@jheyne solution worked for me.
I had problem with the API server not accepting "charset". @jheyne's solution worked perfectly.
@jheyne's answer worked for me.
This is my code.
import 'package:http/http.dart';
final String url = "your api url";
try {
final httpClient = HttpClient();
final request = await httpClient.postUrl(Uri.parse(url));
// headers
request.headers.set('Authorization', 'Bearer $AuthToken');
request.headers.contentType = new ContentType("application", "json");
// body
request.add(
utf8.encode(
jsonEncode(
{
'somebody': somebody,
},
),
),
);
final response = await request.close();
if (response.statusCode == 200) {
final responseBody = await response.transform(utf8.decoder).join();
final result = Model.fromJson(json.decode(responseBody));
}
} on TimeoutException catch (_) {
//print
} on SocketException catch (_) {
//print
}
This is a complete non sense : why is the charset added even if we provide the content-type ? The user input should override the default values, not the opposite !
Are there any updates regarding this topic? Has anyone managed to remove the 'charset=utf8' from the http header or found another solution? My backend also won't accept the request if the charset is specified.
Please specify 'application/vnd.api+json' instead of 'application/vnd.api+json; charset=utf-8' for the Content-Type header value.
Also I use Json Api Specification for Flutter. I cannot set the body first like @jheyne mentioned because the library makes the request.
final httpHandler = LoggingHttpHandler(DartHttp(httpClient),
onRequest: (r) => print('${r.method} ${r.uri} ${r.headers}'),
onResponse: (r) => print('${r.statusCode} ${r.body}'));
final client = JsonApiClient(httpHandler);
var headers = {
'Authorization': 'Bearer $jwtToken',
'Content-Type': 'application/vnd.api+json'
};
client.fetchResourceAt(Uri.parse('$urlTesting$urlPath/code/$invitationCodeString'),headers: headers);
@snowLimit I faced the same issues and decided to use this library https://pub.dev/packages/dio. It's very similar but more flexible and has a lot of interesting features 😉
@jheyne's answer worked for me.
This is my code.
import 'package:http/http.dart'; final String url = "your api url"; try { final httpClient = HttpClient(); final request = await httpClient.postUrl(Uri.parse(url)); // headers request.headers.set('Authorization', 'Bearer $AuthToken'); request.headers.contentType = new ContentType("application", "json"); // body request.add( utf8.encode( jsonEncode( { 'somebody': somebody, }, ), ), ); final response = await request.close(); if (response.statusCode == 200) { final responseBody = await response.transform(utf8.decoder).join(); final result = Model.fromJson(json.decode(responseBody)); } } on TimeoutException catch (_) { //print } on SocketException catch (_) { //print }
it works for me
this is ridiculous migrated to Dio
this is ridiculous migrated to Dio
Unbelievable that you'd have to pick a library over the langs native HTTP client. I've never seen a language where the HTTP client is so bad.
Has anything changed yet?
@brianquinlan I think that this issue should be closed , current http package supports headers and with charsets.
I dont think charsets removal is beneficial.
Otherwise we can help adding more fields such as json , jsonwithnonCharset.
But it doesnt make sense.
It's possible to use Fetch API directly, if you are build for Web Platform only:
import 'dart:js' as js;
var options = js.JsObject(js.context['Object']);
var headers = js.JsObject(js.context['Object']);
headers['Content-Type'] = 'application/json';
options['method'] = 'POST';
options['headers'] = headers;
options['body'] = jsonEncode(<String, String>{
'name': 'Flutter',
});
var result = await js.context.callMethod(
'fetch',
[
'https://some.place.com/foo/bar',
options
],
);
But colleague suggest better way — https://pub.dev/packages/dio
Result looks like:
final dio = Dio();
final response = await dio.post(
'https://some.place.com/foo/bar',
data: jsonEncode(<String, String>{
'name': 'Flutter',
}),
options: Options(
headers: {},
contentType: 'application/json',
),
);
log(jsonEncode(response.data));
This seems to be working as designed and documented.
If you want to assign set the body without setting the Content-Type header implicitly, can't you just assign your data to bodyBytes directly e.g.
final request = Request('GET', myUrl)
..bodyBytes = utf8.encode(myJson)
..headers['content-type'] = 'application/json';
?
If that is the case, please let me know and I will update the documentation to demonstrate this pattern.
this is ridiculous migrated to Dio
Unbelievable that you'd have to pick a library over the langs native HTTP client. I've never seen a language where the HTTP client is so bad.
Let's try to follow the code of conduct and be kind to each other.
@snowLimit I faced the same issues and decided to use this library https://pub.dev/packages/dio. It's very similar but more flexible and has a lot of cool features😉
I did the same thing my friend, Dio is wasome. As soon as I find time I intend to submit a correction to this lib again, add an optional parameter or something like that.
I understand that the solution was denied because I inadequately described the problem, but I intend to redo it soon.
Is there any more feedback on this? Does the pattern suggested in https://github.com/dart-lang/http/issues/184#issuecomment-1634877777 fix the issue?