From e0fe907d194440893c5a1c964d15600284bd209c Mon Sep 17 00:00:00 2001 From: APPALA REDDI Date: Sat, 30 Dec 2023 12:35:10 +0530 Subject: [PATCH 1/7] feat: ability to override content type --- lib/consts.dart | 2 ++ .../request_pane/request_headers.dart | 18 ++++++++++++++++++ lib/utils/header_utils.dart | 11 +++++++++++ lib/widgets/headerfield.dart | 6 +++++- 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/lib/consts.dart b/lib/consts.dart index d881fb86..39cb0dbb 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -305,6 +305,8 @@ const kTypeVideo = 'video'; const kSubTypeDefaultViewOptions = 'all'; +const kContentType = 'Content-Type'; + const kContentTypeMap = { ContentType.json: "$kTypeApplication/$kSubTypeJson", ContentType.text: "$kTypeText/$kSubTypePlain", diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart index 82138db5..0f2cf728 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart @@ -1,4 +1,5 @@ import 'dart:math'; +import 'package:apidash/utils/header_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:davi/davi.dart'; @@ -78,6 +79,23 @@ class EditRequestHeadersState extends ConsumerState { grow: 1, cellBuilder: (_, row) { int idx = row.index; + + if (row.data.name == kContentType) { + return HeaderField( + keyId: "$activeId-$idx-headers-v-$seed", + initialValue: rows[idx].value, + hintText: " Add Header Value", + onChanged: (value) { + rows[idx] = rows[idx].copyWith(value: value); + _onFieldChange(activeId!); + }, + headerSuggestionsCallback: (pattern) { + return getHeaderValueSuggestions(pattern); + }, + colorScheme: Theme.of(context).colorScheme, + ); + } + return CellField( keyId: "$activeId-$idx-headers-v-$seed", initialValue: rows[idx].value, diff --git a/lib/utils/header_utils.dart b/lib/utils/header_utils.dart index 63a456ef..de13f8b4 100644 --- a/lib/utils/header_utils.dart +++ b/lib/utils/header_utils.dart @@ -15,6 +15,7 @@ Map headers = { "Indicates the encoding transformations that have been applied to the entity body of the response.", "Content-Security-Policy": "Controls the sources from which content can be loaded on a web page to mitigate various types of attacks.", + "Content-Type": "Indicates the original media type of the resource (prior to any content encoding applied for sending)", "Cookie": "Used to send previously stored cookies back to the server.", "Cross-Origin-Embedder-Policy": "Controls whether a document is allowed to be embedded in another document.", @@ -70,3 +71,13 @@ List getHeaderSuggestions(String pattern) { ) .toList(); } + +List headerValues = ['application/json', 'text/plain']; + +List getHeaderValueSuggestions(String pattern) { + return headerValues + .where( + (element) => element.contains(pattern.toLowerCase()), + ) + .toList(); +} diff --git a/lib/widgets/headerfield.dart b/lib/widgets/headerfield.dart index 9c678ee3..4ff548e3 100644 --- a/lib/widgets/headerfield.dart +++ b/lib/widgets/headerfield.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:apidash/utils/header_utils.dart'; import 'package:flutter/material.dart'; import 'package:apidash/consts.dart'; @@ -10,12 +12,14 @@ class HeaderField extends StatefulWidget { this.hintText, this.initialValue, this.onChanged, + this.headerSuggestionsCallback, this.colorScheme, }); final String keyId; final String? hintText; final String? initialValue; final void Function(String)? onChanged; + final FutureOr> Function(String)? headerSuggestionsCallback; final ColorScheme? colorScheme; @override @@ -67,7 +71,7 @@ class _HeaderFieldState extends State { title: Text(suggestion), ); }, - suggestionsCallback: headerSuggestionCallback, + suggestionsCallback: widget.headerSuggestionsCallback ?? headerSuggestionCallback, suggestionsBoxDecoration: suggestionBoxDecorations(context), textFieldConfiguration: TextFieldConfiguration( onChanged: widget.onChanged, From e08b40cfb6b09b3842723b83a0dcf0a4d428cb32 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Mon, 1 Jan 2024 09:32:35 +0530 Subject: [PATCH 2/7] Revert "feat: ability to override content type" This reverts commit e0fe907d194440893c5a1c964d15600284bd209c. --- lib/consts.dart | 2 -- .../request_pane/request_headers.dart | 18 ------------------ lib/utils/header_utils.dart | 11 ----------- lib/widgets/headerfield.dart | 6 +----- 4 files changed, 1 insertion(+), 36 deletions(-) diff --git a/lib/consts.dart b/lib/consts.dart index 39cb0dbb..d881fb86 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -305,8 +305,6 @@ const kTypeVideo = 'video'; const kSubTypeDefaultViewOptions = 'all'; -const kContentType = 'Content-Type'; - const kContentTypeMap = { ContentType.json: "$kTypeApplication/$kSubTypeJson", ContentType.text: "$kTypeText/$kSubTypePlain", diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart index 0f2cf728..82138db5 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart @@ -1,5 +1,4 @@ import 'dart:math'; -import 'package:apidash/utils/header_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:davi/davi.dart'; @@ -79,23 +78,6 @@ class EditRequestHeadersState extends ConsumerState { grow: 1, cellBuilder: (_, row) { int idx = row.index; - - if (row.data.name == kContentType) { - return HeaderField( - keyId: "$activeId-$idx-headers-v-$seed", - initialValue: rows[idx].value, - hintText: " Add Header Value", - onChanged: (value) { - rows[idx] = rows[idx].copyWith(value: value); - _onFieldChange(activeId!); - }, - headerSuggestionsCallback: (pattern) { - return getHeaderValueSuggestions(pattern); - }, - colorScheme: Theme.of(context).colorScheme, - ); - } - return CellField( keyId: "$activeId-$idx-headers-v-$seed", initialValue: rows[idx].value, diff --git a/lib/utils/header_utils.dart b/lib/utils/header_utils.dart index de13f8b4..63a456ef 100644 --- a/lib/utils/header_utils.dart +++ b/lib/utils/header_utils.dart @@ -15,7 +15,6 @@ Map headers = { "Indicates the encoding transformations that have been applied to the entity body of the response.", "Content-Security-Policy": "Controls the sources from which content can be loaded on a web page to mitigate various types of attacks.", - "Content-Type": "Indicates the original media type of the resource (prior to any content encoding applied for sending)", "Cookie": "Used to send previously stored cookies back to the server.", "Cross-Origin-Embedder-Policy": "Controls whether a document is allowed to be embedded in another document.", @@ -71,13 +70,3 @@ List getHeaderSuggestions(String pattern) { ) .toList(); } - -List headerValues = ['application/json', 'text/plain']; - -List getHeaderValueSuggestions(String pattern) { - return headerValues - .where( - (element) => element.contains(pattern.toLowerCase()), - ) - .toList(); -} diff --git a/lib/widgets/headerfield.dart b/lib/widgets/headerfield.dart index 4ff548e3..9c678ee3 100644 --- a/lib/widgets/headerfield.dart +++ b/lib/widgets/headerfield.dart @@ -1,5 +1,3 @@ -import 'dart:async'; - import 'package:apidash/utils/header_utils.dart'; import 'package:flutter/material.dart'; import 'package:apidash/consts.dart'; @@ -12,14 +10,12 @@ class HeaderField extends StatefulWidget { this.hintText, this.initialValue, this.onChanged, - this.headerSuggestionsCallback, this.colorScheme, }); final String keyId; final String? hintText; final String? initialValue; final void Function(String)? onChanged; - final FutureOr> Function(String)? headerSuggestionsCallback; final ColorScheme? colorScheme; @override @@ -71,7 +67,7 @@ class _HeaderFieldState extends State { title: Text(suggestion), ); }, - suggestionsCallback: widget.headerSuggestionsCallback ?? headerSuggestionCallback, + suggestionsCallback: headerSuggestionCallback, suggestionsBoxDecoration: suggestionBoxDecorations(context), textFieldConfiguration: TextFieldConfiguration( onChanged: widget.onChanged, From a4042e12d104d1e3c55d09e0d56144f25e77d972 Mon Sep 17 00:00:00 2001 From: Ashita Prasad Date: Mon, 1 Jan 2024 09:33:40 +0530 Subject: [PATCH 3/7] Update header_utils.dart --- lib/utils/header_utils.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/utils/header_utils.dart b/lib/utils/header_utils.dart index 63a456ef..df97a08b 100644 --- a/lib/utils/header_utils.dart +++ b/lib/utils/header_utils.dart @@ -15,6 +15,8 @@ Map headers = { "Indicates the encoding transformations that have been applied to the entity body of the response.", "Content-Security-Policy": "Controls the sources from which content can be loaded on a web page to mitigate various types of attacks.", + "Content-Type": + "Indicates the original media type of the resource (prior to any content encoding applied for sending)", "Cookie": "Used to send previously stored cookies back to the server.", "Cross-Origin-Embedder-Policy": "Controls whether a document is allowed to be embedded in another document.", From 5734b79b1fceb0c3510cb56b817c7e86853b8291 Mon Sep 17 00:00:00 2001 From: APPALA REDDI Date: Mon, 1 Jan 2024 14:58:47 +0530 Subject: [PATCH 4/7] fix: set contenttype only if headers does not have one --- lib/services/http_service.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/services/http_service.dart b/lib/services/http_service.dart index 8265a299..d4cfea2f 100644 --- a/lib/services/http_service.dart +++ b/lib/services/http_service.dart @@ -28,8 +28,10 @@ Future<(http.Response?, Duration?, String?)> request( if (contentLength > 0) { body = requestBody; headers[HttpHeaders.contentLengthHeader] = contentLength.toString(); - headers[HttpHeaders.contentTypeHeader] = - kContentTypeMap[requestModel.requestBodyContentType] ?? ""; + if (!headers.containsKey(HttpHeaders.connectionHeader)) { + headers[HttpHeaders.contentTypeHeader] = + kContentTypeMap[requestModel.requestBodyContentType] ?? ""; + } } } Stopwatch stopwatch = Stopwatch()..start(); From 6efc5d56de06d2a94ee73758e568895e06ff270d Mon Sep 17 00:00:00 2001 From: APPALA REDDI Date: Mon, 1 Jan 2024 15:03:42 +0530 Subject: [PATCH 5/7] fix: wrong header check while overriding content type --- lib/services/http_service.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/http_service.dart b/lib/services/http_service.dart index d4cfea2f..0b6835a2 100644 --- a/lib/services/http_service.dart +++ b/lib/services/http_service.dart @@ -28,7 +28,7 @@ Future<(http.Response?, Duration?, String?)> request( if (contentLength > 0) { body = requestBody; headers[HttpHeaders.contentLengthHeader] = contentLength.toString(); - if (!headers.containsKey(HttpHeaders.connectionHeader)) { + if (!headers.containsKey(HttpHeaders.contentTypeHeader)) { headers[HttpHeaders.contentTypeHeader] = kContentTypeMap[requestModel.requestBodyContentType] ?? ""; } From 5eb91fbaf708ac4f01b0bd9ba89aba17d37c800d Mon Sep 17 00:00:00 2001 From: APPALA REDDI Date: Tue, 2 Jan 2024 09:22:11 +0530 Subject: [PATCH 6/7] fix: content type header presence check --- lib/services/http_service.dart | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/services/http_service.dart b/lib/services/http_service.dart index 0b6835a2..aad8b7f3 100644 --- a/lib/services/http_service.dart +++ b/lib/services/http_service.dart @@ -28,9 +28,10 @@ Future<(http.Response?, Duration?, String?)> request( if (contentLength > 0) { body = requestBody; headers[HttpHeaders.contentLengthHeader] = contentLength.toString(); - if (!headers.containsKey(HttpHeaders.contentTypeHeader)) { - headers[HttpHeaders.contentTypeHeader] = - kContentTypeMap[requestModel.requestBodyContentType] ?? ""; + final hasContentTypeHeader = headers.keys.any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); + if (!hasContentTypeHeader) { + headers[HttpHeaders.contentTypeHeader] = + kContentTypeMap[requestModel.requestBodyContentType] ?? ""; } } } From c765cb378bf6a48d37d56cc44054f6a43cf10e91 Mon Sep 17 00:00:00 2001 From: APPALA REDDI Date: Tue, 2 Jan 2024 09:23:04 +0530 Subject: [PATCH 7/7] refact: codegen to override content-type header --- lib/codegen/dart/http.dart | 5 ++++- lib/codegen/python/http_client.dart | 4 +++- lib/utils/har_utils.dart | 5 ++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/codegen/dart/http.dart b/lib/codegen/dart/http.dart index 67184c25..602b9a73 100644 --- a/lib/codegen/dart/http.dart +++ b/lib/codegen/dart/http.dart @@ -55,8 +55,11 @@ class DartHttpCodeGen { final strContent = CodeExpression(Code('r\'\'\'$body\'\'\'')); dataExp = declareVar('body', type: refer('String')).assign(strContent); - composeHeaders.putIfAbsent(HttpHeaders.contentTypeHeader, + final hasContentTypeHeader = composeHeaders.keys.any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); + if (!hasContentTypeHeader) { + composeHeaders.putIfAbsent(HttpHeaders.contentTypeHeader, () => kContentTypeMap[contentType] ?? ''); + } } Expression? queryParamExp; diff --git a/lib/codegen/python/http_client.dart b/lib/codegen/python/http_client.dart index 83d02676..27f35380 100644 --- a/lib/codegen/python/http_client.dart +++ b/lib/codegen/python/http_client.dart @@ -102,7 +102,9 @@ print(data.decode("utf-8")) var headers = requestModel.headersMap; if (headers.isNotEmpty || hasBody) { hasHeaders = true; - if (hasBody) { + bool hasContentTypeHeader = headers.keys.any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); + + if (hasBody && !hasContentTypeHeader) { headers[HttpHeaders.contentTypeHeader] = kContentTypeMap[requestModel.requestBodyContentType] ?? ""; } diff --git a/lib/utils/har_utils.dart b/lib/utils/har_utils.dart index f0838807..94cdda8b 100644 --- a/lib/utils/har_utils.dart +++ b/lib/utils/har_utils.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:io'; import 'package:apidash/consts.dart'; import 'package:apidash/utils/utils.dart' show getValidRequestUri; import 'package:apidash/models/models.dart' show RequestModel; @@ -129,7 +130,9 @@ Map requestModelToHARJsonRequest( if (headersList != null || hasBody) { var headers = requestModel.headersMap; if (headers.isNotEmpty || hasBody) { - if (hasBody) { + bool hasContentTypeHeader = headers.keys.any((k) => k.toLowerCase() == HttpHeaders.contentTypeHeader); + + if (hasBody && !hasContentTypeHeader) { var m = { "name": "Content-Type", "value": kContentTypeMap[requestModel.requestBodyContentType] ?? ""