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 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 = """ params = {{params}} """; int kParamsPadding = 9; String kTemplateBody = """ payload = r'''{{body}}''' """; String kTemplateJson = """ payload = {{body}} """; String kTemplateHeaders = """ headers = {{headers}} """; int kHeadersPadding = 10; String kTemplateRequest = """ 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"""; String kStringRequestJson = """, json=payload"""; String kStringRequestHeaders = """, headers=headers"""; String kFormDataHeaders = ''' headers['Content-type'] = f'multipart/form-data; boundary={boundary}'; '''; final String kStringRequestEnd = """) print('Status Code:', response.status_code) print('Response Body:', response.text) """; String? getCode( RequestModel requestModel, String defaultUriScheme, ) { try { String result = ""; bool hasQuery = false; bool hasHeaders = false; bool hasBody = false; bool hasJsonBody = false; List formDataList = requestModel.formDataList ?? []; String url = requestModel.url; if (!url.contains("://") && url.isNotEmpty) { url = "$defaultUriScheme://$url"; } var rec = getValidRequestUri(url, requestModel.requestParams); Uri? uri = rec.$1; if (uri != null) { var templateStartUrl = jj.Template(kTemplateStart); result += templateStartUrl.render({ "url": stripUriParams(uri), 'isFormDataRequest': requestModel.isFormDataRequest }); if (uri.hasQuery) { var params = uri.queryParameters; if (params.isNotEmpty) { hasQuery = true; var templateParams = jj.Template(kTemplateParams); var paramsString = kEncoder.convert(params); paramsString = padMultilineString(paramsString, kParamsPadding); result += templateParams.render({"params": paramsString}); } } var method = requestModel.method; var requestBody = requestModel.requestBody; if (kMethodsWithBody.contains(method) && requestBody != null) { var contentLength = utf8.encode(requestBody).length; if (contentLength > 0) { if (requestModel.requestBodyContentType == ContentType.json) { hasJsonBody = true; var templateBody = jj.Template(kTemplateJson); result += templateBody.render({"body": requestBody}); } else { hasBody = true; var templateBody = jj.Template(kTemplateBody); result += templateBody.render({"body": requestBody}); } } } var headersList = requestModel.requestHeaders; if (headersList != null || hasBody) { var headers = requestModel.headersMap; if (headers.isNotEmpty || hasBody) { hasHeaders = true; if (hasBody) { headers[HttpHeaders.contentTypeHeader] = kContentTypeMap[requestModel.requestBodyContentType] ?? ""; } var headersString = kEncoder.convert(headers); headersString = padMultilineString(headersString, kHeadersPadding); var templateHeaders = jj.Template(kTemplateHeaders); 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(), }); if (hasQuery) { result += kStringRequestParams; } if (hasBody || requestModel.isFormDataRequest) { result += kStringRequestBody; } if (hasJsonBody || requestModel.isFormDataRequest) { result += kStringRequestJson; } if (hasHeaders || requestModel.isFormDataRequest) { result += kStringRequestHeaders; } result += kStringRequestEnd; } return result; } catch (e) { return null; } } }