diff --git a/lib/codegen/others/curl.dart b/lib/codegen/others/curl.dart index 5405ee1a..6c60193f 100644 --- a/lib/codegen/others/curl.dart +++ b/lib/codegen/others/curl.dart @@ -10,6 +10,9 @@ class cURLCodeGen { String kTemplateHeader = """ \\ --header '{{name}}: {{value}}' """; + String kTemplateFormData = """ \\ + --form '{{name}}: {{value}}' +"""; String kTemplateBody = """ \\ --data '{{body}}' @@ -48,6 +51,23 @@ class cURLCodeGen { .render({"name": item["name"], "value": item["value"]}); } } + if (harJson['formData'] != null) { + var formDataList = harJson['formData'] as List>; + for (var formData in formDataList) { + var templateFormData = jj.Template(kTemplateFormData); + if (formData['type'] != null && + formData['name'] != null && + formData['value'] != null && + formData['name']!.isNotEmpty && + formData['value']!.isNotEmpty) { + result += templateFormData.render({ + "name": formData["name"], + "value": + "${formData['type'] == 'file' ? '@' : ''}${formData["value"]}", + }); + } + } + } if (harJson["postData"]?["text"] != null) { var templateBody = jj.Template(kTemplateBody); diff --git a/lib/codegen/python/http_client.dart b/lib/codegen/python/http_client.dart index 83d02676..a00038d5 100644 --- a/lib/codegen/python/http_client.dart +++ b/lib/codegen/python/http_client.dart @@ -1,13 +1,23 @@ import 'dart:io'; import 'dart:convert'; +import 'package:apidash/utils/convert_utils.dart'; +import 'package:apidash/utils/extensions/request_model_extension.dart'; import 'package:jinja/jinja.dart' as jj; import 'package:apidash/consts.dart'; import 'package:apidash/utils/utils.dart' show getValidRequestUri, padMultilineString; -import 'package:apidash/models/models.dart' show RequestModel; +import 'package:apidash/models/models.dart' show FormDataModel, RequestModel; class PythonHttpClientCodeGen { final String kTemplateStart = """import http.client +{% if isFormDataRequest %} +import mimetypes +from codecs import encode +import uuid + +headers = {} +boundary = str(uuid.uuid4()) +{% endif %} """; String kTemplateParams = """ @@ -41,6 +51,10 @@ conn = http.client.HTTP{{isHttps}}Connection("{{authority}}")"""; conn.request("{{method}}", "{{path}}"{{queryParamsStr}}"""; + String kTemplateFormDataRequest = """ +conn.request("{{method}}", "{{path}}"{{queryParamsStr}},body=payload, headers=headers +"""; + String kStringRequestBody = """, body= body"""; @@ -55,10 +69,43 @@ data = res.read() print(data.decode("utf-8")) """; + final String kStringFormDataBody = r''' +def build_data_list(fields): + dataList = [] + for field in fields: + name = field.get('name', '') + value = field.get('value', '') + type_ = field.get('type', 'text') + + dataList.append(encode(f'--{boundary}')) + if type_ == 'text': + dataList.append(encode(f'Content-Disposition: form-data; name="{name}"')) + dataList.append(encode('Content-Type: text/plain')) + dataList.append(encode('')) + dataList.append(encode(value)) + elif type_ == 'file': + dataList.append(encode(f'Content-Disposition: form-data; name="{name}"; filename="{value}"')) + dataList.append(encode(f'Content-Type: {mimetypes.guess_type(value)[0] or "application/octet-stream"}')) + dataList.append(encode('')) + dataList.append(open(value, 'rb').read()) + + dataList.append(encode(f'--{boundary}--')) + dataList.append(encode('')) + return dataList +dataList = build_data_list({{fields_list}}) +body = b'\r\n'.join(dataList) +'''; + + String kFormDataHeaders = ''' +headers['Content-type'] = f'multipart/form-data; boundary={boundary}'; +'''; + String? getCode( RequestModel requestModel, String defaultUriScheme, ) { + List formDataList = requestModel.formDataList ?? []; + try { String result = ""; bool hasHeaders = false; @@ -69,8 +116,12 @@ print(data.decode("utf-8")) if (!url.contains("://") && url.isNotEmpty) { url = "$defaultUriScheme://$url"; } - - result += kTemplateStart; + var templateStartUrl = jj.Template(kTemplateStart); + result += templateStartUrl.render( + { + "isFormDataRequest": requestModel.isFormDataRequest, + }, + ); var rec = getValidRequestUri(url, requestModel.requestParams); Uri? uri = rec.$1; @@ -112,13 +163,20 @@ print(data.decode("utf-8")) result += templateHeaders.render({"headers": headersString}); } } - + if (requestModel.isFormDataRequest) { + result += kFormDataHeaders; + var formDataBodyData = jj.Template(kStringFormDataBody); + result += formDataBodyData.render( + { + "fields_list": json.encode(rowsToFormDataMap(formDataList)), + }, + ); + } var templateConnection = jj.Template(kTemplateConnection); result += templateConnection.render({ "isHttps": uri.scheme == "https" ? "S" : "", "authority": uri.authority }); - var templateRequest = jj.Template(kTemplateRequest); result += templateRequest.render({ "method": method.name.toUpperCase(), @@ -126,11 +184,11 @@ print(data.decode("utf-8")) "queryParamsStr": hasQuery ? " + queryParamsStr" : "", }); - if (hasBody) { + if (hasBody || requestModel.isFormDataRequest) { result += kStringRequestBody; } - if (hasHeaders) { + if (hasHeaders || requestModel.isFormDataRequest) { result += kStringRequestHeaders; } @@ -138,6 +196,7 @@ print(data.decode("utf-8")) } return result; } catch (e) { + print(e); return null; } } diff --git a/lib/codegen/python/requests.dart b/lib/codegen/python/requests.dart index af8b3fbe..821f45ed 100644 --- a/lib/codegen/python/requests.dart +++ b/lib/codegen/python/requests.dart @@ -1,16 +1,35 @@ import 'dart:io'; import 'dart:convert'; +import 'package:apidash/utils/convert_utils.dart'; +import 'package:apidash/utils/extensions/request_model_extension.dart'; import 'package:jinja/jinja.dart' as jj; import 'package:apidash/consts.dart'; import 'package:apidash/utils/utils.dart' show getValidRequestUri, padMultilineString, stripUriParams; -import 'package:apidash/models/models.dart' show RequestModel; +import 'package:apidash/models/models.dart' show FormDataModel, RequestModel; class PythonRequestsCodeGen { final String kTemplateStart = """import requests +{% if isFormDataRequest %} +import mimetypes +from codecs import encode +import uuid +headers = {} +boundary = str(uuid.uuid4()) +{% endif %} url = '{{url}}' +"""; + + final String kTemplateFormDataImports = """ +import mimetypes +from codecs import encode +import uuid + +headers = {} +boundary = str(uuid.uuid4()) + """; String kTemplateParams = """ @@ -45,6 +64,32 @@ headers = {{headers}} response = requests.{{method}}(url """; + final String kStringFormDataBody = r''' +def build_data_list(fields): + dataList = [] + for field in fields: + name = field.get('name', '') + value = field.get('value', '') + type_ = field.get('type', 'text') + + dataList.append(encode(f'--{boundary}')) + if type_ == 'text': + dataList.append(encode(f'Content-Disposition: form-data; name="{name}"')) + dataList.append(encode('Content-Type: text/plain')) + dataList.append(encode('')) + dataList.append(encode(value)) + elif type_ == 'file': + dataList.append(encode(f'Content-Disposition: form-data; name="{name}"; filename="{value}"')) + dataList.append(encode(f'Content-Type: {mimetypes.guess_type(value)[0] or "application/octet-stream"}')) + dataList.append(encode('')) + dataList.append(open(value, 'rb').read()) + + dataList.append(encode(f'--{boundary}--')) + dataList.append(encode('')) + return dataList +dataList = build_data_list({{fields_list}}) +payload = b'\r\n'.join(dataList) +'''; String kStringRequestParams = """, params=params"""; String kStringRequestBody = """, data=payload"""; @@ -52,6 +97,9 @@ response = requests.{{method}}(url String kStringRequestJson = """, json=payload"""; String kStringRequestHeaders = """, headers=headers"""; + String kFormDataHeaders = ''' +headers['Content-type'] = f'multipart/form-data; boundary={boundary}'; +'''; final String kStringRequestEnd = """) @@ -69,6 +117,7 @@ print('Response Body:', response.text) bool hasHeaders = false; bool hasBody = false; bool hasJsonBody = false; + List formDataList = requestModel.formDataList ?? []; String url = requestModel.url; if (!url.contains("://") && url.isNotEmpty) { @@ -79,7 +128,10 @@ print('Response Body:', response.text) Uri? uri = rec.$1; if (uri != null) { var templateStartUrl = jj.Template(kTemplateStart); - result += templateStartUrl.render({"url": stripUriParams(uri)}); + result += templateStartUrl.render({ + "url": stripUriParams(uri), + 'isFormDataRequest': requestModel.isFormDataRequest + }); if (uri.hasQuery) { var params = uri.queryParameters; @@ -124,7 +176,15 @@ print('Response Body:', response.text) result += templateHeaders.render({"headers": headersString}); } } - + if (requestModel.isFormDataRequest) { + result += kFormDataHeaders; + var formDataBodyData = jj.Template(kStringFormDataBody); + result += formDataBodyData.render( + { + "fields_list": json.encode(rowsToFormDataMap(formDataList)), + }, + ); + } var templateRequest = jj.Template(kTemplateRequest); result += templateRequest.render({ "method": method.name.toLowerCase(), @@ -134,15 +194,15 @@ print('Response Body:', response.text) result += kStringRequestParams; } - if (hasBody) { + if (hasBody || requestModel.isFormDataRequest) { result += kStringRequestBody; } - if (hasJsonBody) { + if (hasJsonBody || requestModel.isFormDataRequest) { result += kStringRequestJson; } - if (hasHeaders) { + if (hasHeaders || requestModel.isFormDataRequest) { result += kStringRequestHeaders; } diff --git a/lib/utils/extensions/request_model_extension.dart b/lib/utils/extensions/request_model_extension.dart new file mode 100644 index 00000000..95563a05 --- /dev/null +++ b/lib/utils/extensions/request_model_extension.dart @@ -0,0 +1,8 @@ +import 'package:apidash/consts.dart'; +import 'package:apidash/models/models.dart'; + +extension RequestModelExtension on RequestModel { + bool get isFormDataRequest { + return requestBodyContentType == ContentType.formdata; + } +} diff --git a/lib/utils/har_utils.dart b/lib/utils/har_utils.dart index f0838807..c3581f86 100644 --- a/lib/utils/har_utils.dart +++ b/lib/utils/har_utils.dart @@ -1,5 +1,7 @@ import 'dart:convert'; import 'package:apidash/consts.dart'; +import 'package:apidash/models/form_data_model.dart'; +import 'package:apidash/utils/convert_utils.dart'; import 'package:apidash/utils/utils.dart' show getValidRequestUri; import 'package:apidash/models/models.dart' show RequestModel; import 'package:package_info_plus/package_info_plus.dart'; @@ -148,7 +150,11 @@ Map requestModelToHARJsonRequest( } } } - + List formDataList = requestModel.formDataList ?? []; + if (requestModel.requestBodyContentType == ContentType.formdata) { + var formListMap = rowsToFormDataMap(formDataList); + json["formData"] = formListMap; + } if (exportMode) { json["comment"] = ""; json["cookies"] = [];