Skip to content

Har importer #730

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

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/consts.dart
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ enum CodegenLanguage {
enum ImportFormat {
curl("cURL"),
postman("Postman Collection v2.1"),
insomnia("Insomnia v4");
insomnia("Insomnia v4"),
har("Har v1.2");

const ImportFormat(this.label);
final String label;
Expand Down
1 change: 1 addition & 0 deletions lib/importer/importer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class Importer {
.toList(),
ImportFormat.postman => PostmanIO().getHttpRequestModelList(content),
ImportFormat.insomnia => InsomniaIO().getHttpRequestModelList(content),
ImportFormat.har => HarParserIO().getHttpRequestModelList(content),
};
}
}
Expand Down
135 changes: 135 additions & 0 deletions packages/apidash_core/lib/import_export/har_io.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import 'package:har_parser/har_parser.dart' as hp;
import 'package:seed/seed.dart';
import '../consts.dart';
import '../models/models.dart';
import '../utils/utils.dart';

class HarParserIO {
List<(String?, HttpRequestModel)>? getHttpRequestModelList(String content) {
content = content.trim();
try {
final hl = hp.harLogFromJsonStr(content);
final requests = hp.getRequestsFromHarLog(hl);
return requests
.map((req) => (req.$2.url, harRequestToHttpRequestModel(req.$2)))
.toList();
} catch (e) {
return null;
}
}

HttpRequestModel harRequestToHttpRequestModel(hp.Request request) {
HTTPVerb method;

try {
method = HTTPVerb.values.byName((request.method ?? "").toLowerCase());
} catch (e) {
method = kDefaultHttpMethod;
}
String url = stripUrlParams(request.url ?? "");
List<NameValueModel> headers = [];
List<bool> isHeaderEnabledList = [];

List<NameValueModel> params = [];
List<bool> isParamEnabledList = [];

for (var header in request.headers ?? <hp.Header>[]) {
var name = header.name ?? "";
var value = header.value;
var activeHeader = header.disabled ?? false;
headers.add(NameValueModel(name: name, value: value));
isHeaderEnabledList.add(!activeHeader);
}

for (var query in request.queryString ?? <hp.Query>[]) {
var name = query.name ?? "";
var value = query.value;
var activeQuery = query.disabled ?? false;
params.add(NameValueModel(name: name, value: value));
isParamEnabledList.add(!activeQuery);
}

ContentType bodyContentType = kDefaultContentType;
String? body;
List<FormDataModel>? formData = [];

if (request.postData?.mimeType == "application/json") {
bodyContentType = ContentType.json;
body = request.postData?.text;
}
FormDataType formDataType = FormDataType.text;
if (request.postData?.mimeType == "application/x-www-form-urlencoded") {
bodyContentType = ContentType.formdata;
var formDataStr = request.postData?.text;
Map<String, String> parsedData = parseFormData(formDataStr);
parsedData.forEach((key, value) {
formDataType = FormDataType.text;
var name = key ?? "";
var val = value ?? "";
formData.add(FormDataModel(
name: name,
value: val,
type: formDataType,
));
});
}

if (request.postData?.mimeType == "multipart/form-data") {
bodyContentType = ContentType.formdata;
var name, val;
for (var fd in request.postData?.params ?? <hp.Param>[]) {
name = fd.name;
if (fd.contentType == "text/plain") {
formDataType = FormDataType.text;
val = fd.value;
} else {
formDataType = FormDataType.file;
val = fd.fileName;
}
formData.add(FormDataModel(
name: name,
value: val,
type: formDataType,
));
}
}

return HttpRequestModel(
method: method,
url: url,
headers: headers,
params: params,
isHeaderEnabledList: isHeaderEnabledList,
isParamEnabledList: isParamEnabledList,
body: body,
bodyContentType: bodyContentType,
formData: formData);
}

Map<String, String> parseFormData(String? data) {
// Return an empty map if the input is null or empty
if (data == null || data.isEmpty) {
return {};
}
// Split the input string into individual key-value pairs
var pairs = data.split('&');

// Create a Map to store key-value pairs
Map<String, String> result = {};

// Loop through the pairs and split them into keys and values
for (var pair in pairs) {
var keyValue = pair.split('=');

// Ensure the pair contains both key and value
if (keyValue.length == 2) {
var key = Uri.decodeComponent(keyValue[0]);
var value = Uri.decodeComponent(keyValue[1]);

result[key] = value;
}
}

return result;
}
}
1 change: 1 addition & 0 deletions packages/apidash_core/lib/import_export/import_export.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export 'curl_io.dart';
export 'postman_io.dart';
export 'insomnia_io.dart';
export 'har_io.dart';
2 changes: 2 additions & 0 deletions packages/apidash_core/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ dependencies:
path: ../insomnia_collection
postman:
path: ../postman
har_parser:
path: ../har_parser
seed: ^0.0.3
xml: ^6.3.0

Expand Down
3 changes: 3 additions & 0 deletions packages/apidash_core/pubspec_overrides.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# melos_managed_dependency_overrides: har_parser
# melos_managed_dependency_overrides: curl_parser,insomnia_collection,postman,seed
dependency_overrides:
curl_parser:
path: ../curl_parser
har_parser:
path: ..\\har_parser
insomnia_collection:
path: ../insomnia_collection
postman:
Expand Down
31 changes: 31 additions & 0 deletions packages/har_parser/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/

# IntelliJ related
*.iml
*.ipr
*.iws
.idea/

# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/

# Flutter/Dart/Pub related
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
/pubspec.lock
**/doc/api/
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
build/
3 changes: 3 additions & 0 deletions packages/har_parser/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 0.0.1

* TODO: Describe initial release.
Loading