Skip to content

Commit 9b54b3b

Browse files
authored
Merge pull request #730 from ayaan-md-blr/har_importer
Har importer
2 parents 583a113 + 386b363 commit 9b54b3b

24 files changed

+4519
-3
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ API Dash can be downloaded from the links below:
105105
| Insomnia ||
106106
| OpenAPI | https://github.com/foss42/apidash/issues/121 |
107107
| hurl | https://github.com/foss42/apidash/issues/123 |
108-
| HAR | https://github.com/foss42/apidash/issues/122 |
108+
| HAR | |
109109

110110

111111
**↗️ Create & Customize API Requests**

lib/consts.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,8 @@ enum CodegenLanguage {
144144
enum ImportFormat {
145145
curl("cURL"),
146146
postman("Postman Collection v2.1"),
147-
insomnia("Insomnia v4");
147+
insomnia("Insomnia v4"),
148+
har("Har v1.2");
148149

149150
const ImportFormat(this.label);
150151
final String label;

lib/importer/importer.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class Importer {
1313
.toList(),
1414
ImportFormat.postman => PostmanIO().getHttpRequestModelList(content),
1515
ImportFormat.insomnia => InsomniaIO().getHttpRequestModelList(content),
16+
ImportFormat.har => HarParserIO().getHttpRequestModelList(content),
1617
};
1718
}
1819
}
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import 'package:har/har.dart' as har;
2+
import 'package:seed/seed.dart';
3+
import '../consts.dart';
4+
import '../models/models.dart';
5+
import '../utils/utils.dart';
6+
7+
class HarParserIO {
8+
List<(String?, HttpRequestModel)>? getHttpRequestModelList(String content) {
9+
content = content.trim();
10+
try {
11+
final hl = har.harLogFromJsonStr(content);
12+
final requests = har.getRequestsFromHarLog(hl);
13+
return requests
14+
.map((req) => (req.$2.url, harRequestToHttpRequestModel(req.$2)))
15+
.toList();
16+
} catch (e) {
17+
return null;
18+
}
19+
}
20+
21+
HttpRequestModel harRequestToHttpRequestModel(har.Request request) {
22+
HTTPVerb method;
23+
24+
try {
25+
method = HTTPVerb.values.byName((request.method ?? "").toLowerCase());
26+
} catch (e) {
27+
method = kDefaultHttpMethod;
28+
}
29+
String url = stripUrlParams(request.url ?? "");
30+
List<NameValueModel> headers = [];
31+
List<bool> isHeaderEnabledList = [];
32+
33+
List<NameValueModel> params = [];
34+
List<bool> isParamEnabledList = [];
35+
36+
for (var header in request.headers ?? <har.Header>[]) {
37+
var name = header.name ?? "";
38+
var value = header.value;
39+
var activeHeader = header.disabled ?? false;
40+
headers.add(NameValueModel(name: name, value: value));
41+
isHeaderEnabledList.add(!activeHeader);
42+
}
43+
44+
for (var query in request.queryString ?? <har.Query>[]) {
45+
var name = query.name ?? "";
46+
var value = query.value;
47+
var activeQuery = query.disabled ?? false;
48+
params.add(NameValueModel(name: name, value: value));
49+
isParamEnabledList.add(!activeQuery);
50+
}
51+
52+
ContentType bodyContentType = kDefaultContentType;
53+
String? body;
54+
List<FormDataModel>? formData = [];
55+
56+
if (request.postData?.mimeType == "application/json") {
57+
bodyContentType = ContentType.json;
58+
body = request.postData?.text;
59+
}
60+
FormDataType formDataType = FormDataType.text;
61+
if (request.postData?.mimeType == "application/x-www-form-urlencoded") {
62+
bodyContentType = ContentType.formdata;
63+
var formDataStr = request.postData?.text;
64+
Map<String, String> parsedData = parseFormData(formDataStr);
65+
parsedData.forEach((key, value) {
66+
formDataType = FormDataType.text;
67+
var name = key;
68+
var val = value;
69+
formData.add(FormDataModel(
70+
name: name,
71+
value: val,
72+
type: formDataType,
73+
));
74+
});
75+
}
76+
77+
if (request.postData?.mimeType == "multipart/form-data") {
78+
bodyContentType = ContentType.formdata;
79+
String? name, val;
80+
for (var fd in request.postData?.params ?? <har.Param>[]) {
81+
name = fd.name;
82+
if (fd.contentType == "text/plain") {
83+
formDataType = FormDataType.text;
84+
val = fd.value;
85+
} else {
86+
formDataType = FormDataType.file;
87+
val = fd.fileName;
88+
}
89+
formData.add(FormDataModel(
90+
name: name ?? "",
91+
value: val ?? "",
92+
type: formDataType,
93+
));
94+
}
95+
}
96+
97+
return HttpRequestModel(
98+
method: method,
99+
url: url,
100+
headers: headers,
101+
params: params,
102+
isHeaderEnabledList: isHeaderEnabledList,
103+
isParamEnabledList: isParamEnabledList,
104+
body: body,
105+
bodyContentType: bodyContentType,
106+
formData: formData);
107+
}
108+
109+
Map<String, String> parseFormData(String? data) {
110+
// Return an empty map if the input is null or empty
111+
if (data == null || data.isEmpty) {
112+
return {};
113+
}
114+
// Split the input string into individual key-value pairs
115+
var pairs = data.split('&');
116+
117+
// Create a Map to store key-value pairs
118+
Map<String, String> result = {};
119+
120+
// Loop through the pairs and split them into keys and values
121+
for (var pair in pairs) {
122+
var keyValue = pair.split('=');
123+
124+
// Ensure the pair contains both key and value
125+
if (keyValue.length == 2) {
126+
var key = Uri.decodeComponent(keyValue[0]);
127+
var value = Uri.decodeComponent(keyValue[1]);
128+
129+
result[key] = value;
130+
}
131+
}
132+
133+
return result;
134+
}
135+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export 'curl_io.dart';
22
export 'postman_io.dart';
33
export 'insomnia_io.dart';
4+
export 'har_io.dart';

packages/apidash_core/pubspec.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ dependencies:
2222
json5: ^0.8.2
2323
postman:
2424
path: ../postman
25+
har:
26+
path: ../har
2527
seed: ^0.0.3
2628
xml: ^6.3.0
2729

packages/apidash_core/pubspec_overrides.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
# melos_managed_dependency_overrides: curl_parser,insomnia_collection,postman,seed
1+
# melos_managed_dependency_overrides: curl_parser,insomnia_collection,postman,seed,har
22
dependency_overrides:
33
curl_parser:
44
path: ../curl_parser
5+
har:
6+
path: ../har
57
insomnia_collection:
68
path: ../insomnia_collection
79
postman:

packages/har/.gitignore

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Miscellaneous
2+
*.class
3+
*.log
4+
*.pyc
5+
*.swp
6+
.DS_Store
7+
.atom/
8+
.buildlog/
9+
.history
10+
.svn/
11+
migrate_working_dir/
12+
13+
# IntelliJ related
14+
*.iml
15+
*.ipr
16+
*.iws
17+
.idea/
18+
19+
# The .vscode folder contains launch configuration and tasks you configure in
20+
# VS Code which you may wish to be included in version control, so this line
21+
# is commented out by default.
22+
#.vscode/
23+
24+
# Flutter/Dart/Pub related
25+
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
26+
/pubspec.lock
27+
**/doc/api/
28+
.dart_tool/
29+
.flutter-plugins
30+
.flutter-plugins-dependencies
31+
build/

packages/har/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## 0.0.1
2+
3+
* TODO: Describe initial release.

0 commit comments

Comments
 (0)