Merge pull request #818 from WannaCry016/patch-5

Fix Issue #630 Unable to override Content-Type header charset
This commit is contained in:
Ankit Mahato
2025-04-20 03:11:08 +05:30
committed by GitHub
5 changed files with 130 additions and 23 deletions

View File

@ -23,4 +23,10 @@ extension MapExtension on Map {
String? getValueContentType() {
return this[getKeyContentType()];
}
Map removeKeyContentType() {
removeWhere(
(key, value) => key.toLowerCase() == HttpHeaders.contentTypeHeader);
return this;
}
}

View File

@ -4,6 +4,7 @@ import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:seed/seed.dart';
import '../consts.dart';
import '../extensions/extensions.dart';
import '../models/models.dart';
import '../utils/utils.dart';
import 'http_client_manager.dart';
@ -33,6 +34,7 @@ Future<(HttpResponse?, Duration?, String?)> sendHttpRequest(
if (uriRec.$1 != null) {
Uri requestUrl = uriRec.$1!;
Map<String, String> headers = requestModel.enabledHeadersMap;
bool overrideContentType = false;
HttpResponse? response;
String? body;
try {
@ -43,16 +45,15 @@ Future<(HttpResponse?, Duration?, String?)> sendHttpRequest(
if (kMethodsWithBody.contains(requestModel.method)) {
var requestBody = requestModel.body;
if (requestBody != null && !isMultiPartRequest) {
var contentLength = utf8.encode(requestBody).length;
if (contentLength > 0) {
body = requestBody;
headers[HttpHeaders.contentLengthHeader] =
contentLength.toString();
if (!requestModel.hasContentTypeHeader) {
headers[HttpHeaders.contentTypeHeader] =
requestModel.bodyContentType.header;
}
if (requestBody != null &&
!isMultiPartRequest &&
requestBody.isNotEmpty) {
body = requestBody;
if (requestModel.hasContentTypeHeader) {
overrideContentType = true;
} else {
headers[HttpHeaders.contentTypeHeader] =
requestModel.bodyContentType.header;
}
}
if (isMultiPartRequest) {
@ -82,18 +83,28 @@ Future<(HttpResponse?, Duration?, String?)> sendHttpRequest(
return (convertedMultiPartResponse, stopwatch.elapsed, null);
}
}
response = switch (requestModel.method) {
HTTPVerb.get => await client.get(requestUrl, headers: headers),
HTTPVerb.head => await client.head(requestUrl, headers: headers),
HTTPVerb.post =>
await client.post(requestUrl, headers: headers, body: body),
HTTPVerb.put =>
await client.put(requestUrl, headers: headers, body: body),
HTTPVerb.patch =>
await client.patch(requestUrl, headers: headers, body: body),
HTTPVerb.delete =>
await client.delete(requestUrl, headers: headers, body: body),
};
switch (requestModel.method) {
case HTTPVerb.get:
response = await client.get(requestUrl, headers: headers);
break;
case HTTPVerb.head:
response = await client.head(requestUrl, headers: headers);
break;
case HTTPVerb.post:
case HTTPVerb.put:
case HTTPVerb.patch:
case HTTPVerb.delete:
final request = prepareHttpRequest(
url: requestUrl,
method: requestModel.method.name.toUpperCase(),
headers: headers,
body: body,
overrideContentType: overrideContentType,
);
final streamed = await client.send(request);
response = await http.Response.fromStream(streamed);
break;
}
}
if (apiType == APIType.graphql) {
var requestBody = getGraphQLBody(requestModel);
@ -131,3 +142,27 @@ Future<(HttpResponse?, Duration?, String?)> sendHttpRequest(
void cancelHttpRequest(String? requestId) {
httpClientManager.cancelRequest(requestId);
}
http.Request prepareHttpRequest({
required Uri url,
required String method,
required Map<String, String> headers,
required String? body,
bool overrideContentType = false,
}) {
var request = http.Request(method, url);
if (headers.getValueContentType() != null) {
request.headers[HttpHeaders.contentTypeHeader] =
headers.getValueContentType()!;
if (!overrideContentType) {
headers.removeKeyContentType();
}
}
if (body != null) {
request.body = body;
headers[HttpHeaders.contentLengthHeader] =
request.bodyBytes.length.toString();
}
request.headers.addAll(headers);
return request;
}

View File

@ -441,3 +441,28 @@ const httpRequestModelPost11 = HttpRequestModel(
"text": "I LOVE Flutter"
}""",
);
/// POST request model with default (utf-8) content type charset
const httpRequestModelPost12 = HttpRequestModel(
method: HTTPVerb.post,
url: 'https://api.apidash.dev/case/lower',
bodyContentType: ContentType.json,
body: r"""{
"text": "I LOVE Flutter"
}""",
);
/// POST request model with charset override (latin1)
const httpRequestModelPost13 = HttpRequestModel(
method: HTTPVerb.post,
url: 'https://api.apidash.dev/case/lower',
headers: [
NameValueModel(
name: 'Content-Type', value: 'application/json; charset=latin1'),
],
isHeaderEnabledList: [true],
bodyContentType: ContentType.json,
body: r"""{
"text": "I LOVE Flutter"
}""",
);

View File

@ -233,8 +233,23 @@ const requestModelGetBadSSL = RequestModel(
httpRequestModel: httpRequestModelGetBadSSL,
);
/// POST request model with content type override having no charset
const requestModelPost11 = RequestModel(
id: 'post11',
apiType: APIType.rest,
httpRequestModel: httpRequestModelPost11,
);
/// POST request model with default (utf-8) content type charset
const requestModelPost12 = RequestModel(
id: 'post12',
apiType: APIType.rest,
httpRequestModel: httpRequestModelPost12,
);
/// POST request model with charset override (latin1)
const requestModelPost13 = RequestModel(
id: 'post13',
apiType: APIType.rest,
httpRequestModel: httpRequestModelPost13,
);

View File

@ -58,10 +58,36 @@ void main() {
final responseData = responseModel.fromResponse(response: responseRec.$1!);
expect(responseData.statusCode, 200);
expect(responseData.body, '{"data":"i love flutter"}');
expect(responseData.contentType, 'application/json; charset=utf-8');
expect(responseData.contentType, 'application/json');
expect(responseData.requestHeaders?['content-type'], 'application/json');
});
test('Testing default contentType charset added by dart', () async {
var responseRec = await sendHttpRequest(
requestModelPost12.id,
requestModelPost12.apiType,
requestModelPost12.httpRequestModel!,
);
final responseData = responseModel.fromResponse(response: responseRec.$1!);
expect(responseData.statusCode, 200);
expect(responseData.requestHeaders?['content-type'],
'application/json; charset=utf-8');
});
test('Testing latin1 charset added by user', () async {
var responseRec = await sendHttpRequest(
requestModelPost13.id,
requestModelPost13.apiType,
requestModelPost13.httpRequestModel!,
);
final responseData = responseModel.fromResponse(response: responseRec.$1!);
expect(responseData.statusCode, 200);
expect(responseData.requestHeaders?['content-type'],
'application/json; charset=latin1');
});
test('Testing fromResponse for Bad SSL with certificate check', () async {
var responseRec = await sendHttpRequest(
requestModelGetBadSSL.id,