Skip to content
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

Remove charset from "Content-Type" header #184

Closed
Pandazaur opened this issue Jul 19, 2018 · 24 comments · Fixed by #1014
Closed

Remove charset from "Content-Type" header #184

Pandazaur opened this issue Jul 19, 2018 · 24 comments · Fixed by #1014
Assignees
Labels
type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)

Comments

@Pandazaur
Copy link

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

@ghost
Copy link

ghost commented Aug 23, 2018

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.

@ghost ghost added the type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) label Aug 23, 2018
@jheyne
Copy link

jheyne commented Feb 15, 2019

Work-around: Set the body first (this sets default headers), then set the headers.

@jefioliveira
Copy link

I have the same problem, however the above solution did not work in my case.

jefioliveira added a commit to jefioliveira/http that referenced this issue Feb 22, 2019
Remove charset from "Content-Type" header

Now the null value will be reflected for the charset in the header.
jefioliveira added a commit to jefioliveira/http that referenced this issue Feb 23, 2019
Remove charset from "Content-Type" header

Now the null value will be reflected for the charset in the header.
jefioliveira added a commit to jefioliveira/http that referenced this issue Feb 23, 2019
Remove charset from "Content-Type" header

Now the null value will be reflected for the charset in the header.
jefioliveira added a commit to jefioliveira/http that referenced this issue Feb 23, 2019
Remove charset from "Content-Type" header

Now the null value will be reflected for the charset in the header.
@jheyne
Copy link

jheyne commented Feb 23, 2019

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';

jefioliveira added a commit to jefioliveira/http that referenced this issue May 15, 2019
Remove charset from "Content-Type" header

Now the null value will be reflected for the charset in the header.
@aloisdeniel
Copy link

I encountered the same issue, but @jheyne workaround didn't work for me.

We should be able to write request.encoding = null.

@cmregazzo
Copy link

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

@Dudecor3
Copy link

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

@Multiamory
Copy link

Multiamory commented Jan 27, 2020

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?

@vikalpnagar
Copy link

@jheyne solution worked for me.

@AndreasLymalmSigma
Copy link

I had problem with the API server not accepting "charset". @jheyne's solution worked perfectly.

@shin
Copy link

shin commented Aug 13, 2020

@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
    }

@monisnap-julien
Copy link

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 !

@frozen-syntax
Copy link

frozen-syntax commented Oct 27, 2020

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

@monisnap-julien
Copy link

@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 😉

@Erarshad
Copy link

@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

@martipello
Copy link

this is ridiculous migrated to Dio

@Dud3core-webdev
Copy link

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.

asmith26 added a commit to asmith26/http that referenced this issue Apr 18, 2022
maporcho added a commit to nubank/http_interceptor that referenced this issue Nov 10, 2022
Preventing charset from being added to the "content-type" header. Based
on a workaround for a know http bug:
dart-lang/http#184 (comment).
@LeonManolo
Copy link

Has anything changed yet?

@seifibrahim32
Copy link

seifibrahim32 commented Apr 22, 2023

@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.

@astnt
Copy link

astnt commented Jun 12, 2023

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

@brianquinlan
Copy link
Collaborator

brianquinlan commented Jul 13, 2023

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.

@brianquinlan
Copy link
Collaborator

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.

@jefioliveira
Copy link

@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.

@brianquinlan
Copy link
Collaborator

Is there any more feedback on this? Does the pattern suggested in #184 (comment) fix the issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)
Projects
None yet
Development

Successfully merging a pull request may close this issue.