Skip to content

Commit e20ffbb

Browse files
committed
Merge branch 'main' of https://github.com/foss42/apidash into add-rust-curl-codegen
2 parents b7bf324 + 09c572c commit e20ffbb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+12019
-2312
lines changed

CONTRIBUTING.md

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -129,20 +129,27 @@ flutter test test/widgets/codegen_previewer_test.dart
129129

130130
Instead of copy pasting from pub.dev, it is recommended that you use `flutter pub add package_name` to add a new package to `pubspec.yaml`. You can read more [here](https://docs.flutter.dev/packages-and-plugins/using-packages#adding-a-package-dependency-to-an-app-using-flutter-pub-add).
131131

132-
## Troubleshooting Common Issues
132+
## Platform-specific Additional Instructions
133133

134-
### Network Connection Issues on macOS
134+
### macOS
135135

136-
If you encounter a network connection error similar to the following while running your Flutter app on macOS:
136+
Add below keys to `macos/Runner/DebugProfile.entitlements` and `macos/Runner/Release.entitlements`.
137137

138138
```
139-
ClientException with SocketException: Connection failed (OS Error: Operation not permitted, errno = 1)
139+
<key>com.apple.security.network.server</key>
140+
<true/>
141+
<key>com.apple.security.network.client</key>
142+
<true/>
143+
<key>com.apple.security.files.downloads.read-write</key>
144+
<true/>
145+
<key>com.apple.security.files.user-selected.read-write</key>
146+
<true/>
140147
```
141-
Add below key to `macos/Runner/DebugProfile.entitlements` and `macos/Runner/Release.entitlements`.
148+
149+
If not added, you can encounter a network connection error similar to the following while running your Flutter app on macOS:
142150

143151
```
144-
<key>com.apple.security.network.client</key>
145-
<true/>
152+
ClientException with SocketException: Connection failed (OS Error: Operation not permitted, errno = 1)
146153
```
147154

148155
You can read more [here](https://docs.flutter.dev/platform-integration/macos/building#setting-up-entitlements)

README.md

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,17 @@
22

33
[![Discord Server Invite](https://img.shields.io/badge/DISCORD-JOIN%20SERVER-5663F7?style=for-the-badge&logo=discord&logoColor=white)](https://bit.ly/heyfoss)
44

5-
We are participating in GSoC 2024 🎉 [More Details ...](https://summerofcode.withgoogle.com/programs/2024/organizations/api-dash)
5+
🚨 We are participating in GSoC 2024 🎉
6+
7+
<img src="https://github.com/foss42/apidash/assets/615622/493ce57f-06c3-4789-b7ae-9fa63bca8183" alt="GSoC" width="500">
8+
9+
| | Link |
10+
|--|--|
11+
| Learn about GSoC | [Link](https://summerofcode.withgoogle.com) |
12+
| Organization page on GSoC | [Link](https://summerofcode.withgoogle.com/programs/2024/organizations/api-dash) |
13+
| Project Ideas List | [Link](https://github.com/foss42/apidash/discussions/112) |
14+
| Application Guide | [Link](https://github.com/foss42/apidash/discussions/111) |
15+
| Discord Channel | [Link](https://discord.com/invite/2s49SCNfyJ) |
616

717
### Please support this initiative by giving this project a Star ⭐️
818

@@ -113,18 +123,28 @@ API Dash can be downloaded from the links below:
113123

114124
API Dash currently supports API integration code generation for the following languages/libraries.
115125

116-
| Language | Library |
117-
| ---------------------- | ------------- |
118-
| cURL | |
119-
| HAR | |
120-
| Dart | `http` |
121-
| JavaScript | `axios` |
122-
| JavaScript | `fetch` |
123-
| JavaScript (`node.js`) | `axios` |
124-
| JavaScript (`node.js`) | `fetch` |
125-
| Python | `http.client` |
126-
| Python | `requests` |
127-
| Kotlin | `okhttp3` |
126+
| Language | Library | Comment/Issues |
127+
| ---------------------- | ------------- | ------- |
128+
| cURL | | |
129+
| HAR | | |
130+
| Dart | `http` | |
131+
| Dart | `dio` | |
132+
| Go | `net/http` | |
133+
| JavaScript | `axios` | |
134+
| JavaScript | `fetch` | |
135+
| JavaScript (`node.js`) | `axios` | |
136+
| JavaScript (`node.js`) | `fetch` | |
137+
| Python | `requests` | |
138+
| Python | `http.client` | |
139+
| Kotlin | `okhttp3` | |
140+
| Rust | `reqwest` | |
141+
| Rust | `ureq` | |
142+
| Rust | `Actix Client` | |
143+
| Java | `asynchttpclient` | https://github.com/foss42/apidash/issues/136 |
144+
| Java | `HttpClient` | https://github.com/foss42/apidash/issues/137 |
145+
| Java | `okhttp3` | |
146+
| Julia | `HTTP` | https://github.com/foss42/apidash/issues/154 |
147+
| PHP | `guzzle` | https://github.com/foss42/apidash/issues/143 |
128148

129149
We welcome contributions to support other programming languages/libraries/frameworks. Please check out more details [here](https://github.com/foss42/apidash/discussions/80).
130150

lib/codegen/codegen.dart

Lines changed: 53 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,87 @@
11
import 'package:apidash/codegen/rust/curl-rust.dart';
22
import 'package:apidash/models/models.dart' show RequestModel;
33
import 'package:apidash/consts.dart';
4+
import 'package:apidash/utils/utils.dart' show getNewUuid;
45
import 'dart/http.dart';
56
import 'dart/dio.dart';
7+
import 'go/http.dart';
68
import 'kotlin/okhttp.dart';
9+
import 'php/guzzle.dart';
710
import 'python/http_client.dart';
811
import 'python/requests.dart';
12+
import 'rust/actix.dart';
13+
import 'rust/reqwest.dart';
14+
import 'rust/ureq.dart';
915
import 'js/axios.dart';
1016
import 'js/fetch.dart';
1117
import 'others/har.dart';
1218
import 'others/curl.dart';
19+
import 'julia/http.dart';
20+
import 'java/okhttp.dart';
21+
import 'java/async_http_client.dart';
22+
import 'java/httpclient.dart';
1323

1424
class Codegen {
1525
String? getCode(
1626
CodegenLanguage codegenLanguage,
1727
RequestModel requestModel,
18-
String defaultUriScheme,
19-
) {
28+
String defaultUriScheme, {
29+
String? boundary,
30+
}) {
31+
String url = requestModel.url;
32+
33+
if (url.isEmpty) {
34+
url = kDefaultUri;
35+
}
36+
if (!url.contains("://") && url.isNotEmpty) {
37+
url = "$defaultUriScheme://$url";
38+
}
39+
var rM = requestModel.copyWith(url: url);
40+
2041
switch (codegenLanguage) {
2142
case CodegenLanguage.curl:
22-
return cURLCodeGen().getCode(requestModel, defaultUriScheme);
43+
return cURLCodeGen().getCode(rM);
2344
case CodegenLanguage.har:
24-
return HARCodeGen().getCode(requestModel, defaultUriScheme);
45+
return HARCodeGen().getCode(rM, defaultUriScheme, boundary: boundary);
2546
case CodegenLanguage.dartHttp:
26-
return DartHttpCodeGen().getCode(requestModel, defaultUriScheme);
47+
return DartHttpCodeGen().getCode(rM);
2748
case CodegenLanguage.dartDio:
28-
return DartDioCodeGen().getCode(requestModel, defaultUriScheme);
49+
return DartDioCodeGen().getCode(rM);
50+
case CodegenLanguage.goHttp:
51+
return GoHttpCodeGen().getCode(rM);
2952
case CodegenLanguage.jsAxios:
30-
return AxiosCodeGen().getCode(requestModel, defaultUriScheme);
53+
return AxiosCodeGen().getCode(rM);
3154
case CodegenLanguage.jsFetch:
32-
return FetchCodeGen().getCode(requestModel, defaultUriScheme);
55+
return FetchCodeGen().getCode(rM);
3356
case CodegenLanguage.nodejsAxios:
34-
return AxiosCodeGen(isNodeJs: true)
35-
.getCode(requestModel, defaultUriScheme);
57+
return AxiosCodeGen(isNodeJs: true).getCode(rM);
3658
case CodegenLanguage.nodejsFetch:
37-
return FetchCodeGen(isNodeJs: true)
38-
.getCode(requestModel, defaultUriScheme);
59+
return FetchCodeGen(isNodeJs: true).getCode(rM);
60+
case CodegenLanguage.javaAsyncHttpClient:
61+
return JavaAsyncHttpClientGen().getCode(rM);
62+
case CodegenLanguage.javaHttpClient:
63+
return JavaHttpClientCodeGen().getCode(rM);
64+
case CodegenLanguage.javaOkHttp:
65+
return JavaOkHttpCodeGen().getCode(rM);
66+
case CodegenLanguage.juliaHttp:
67+
return JuliaHttpClientCodeGen().getCode(rM);
3968
case CodegenLanguage.kotlinOkHttp:
40-
return KotlinOkHttpCodeGen().getCode(requestModel, defaultUriScheme);
69+
return KotlinOkHttpCodeGen().getCode(rM);
4170
case CodegenLanguage.pythonHttpClient:
4271
return PythonHttpClientCodeGen()
43-
.getCode(requestModel, defaultUriScheme);
72+
.getCode(rM, boundary: boundary ?? getNewUuid());
4473
case CodegenLanguage.pythonRequests:
45-
return PythonRequestsCodeGen().getCode(requestModel, defaultUriScheme);
74+
return PythonRequestsCodeGen().getCode(rM, boundary: boundary);
75+
case CodegenLanguage.rustActix:
76+
return RustActixCodeGen().getCode(rM, boundary: boundary);
77+
case CodegenLanguage.rustReqwest:
78+
return RustReqwestCodeGen().getCode(rM);
4679
case CodegenLanguage.rustCurl:
47-
return RustCurlCodeGen().getCode(requestModel, defaultUriScheme);
80+
return RustCurlCodeGen().getCode(rM);
81+
case CodegenLanguage.rustUreq:
82+
return RustUreqCodeGen().getCode(rM, boundary: boundary);
83+
case CodegenLanguage.phpGuzzle:
84+
return PhpGuzzleCodeGen().getCode(rM);
4885
}
4986
}
5087
}

lib/codegen/codegen_utils.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
String jsonToPyDict(String jsonString) {
2+
Map<String, String> replaceWithMap = {
3+
"null": "None",
4+
"true": "True",
5+
"false": "False"
6+
};
7+
String pyDict = jsonString;
8+
for (var k in replaceWithMap.keys) {
9+
RegExp regExp = RegExp(k + r'(?=([^"]*"[^"]*")*[^"]*$)');
10+
pyDict = pyDict.replaceAllMapped(regExp, (match) {
11+
return replaceWithMap[match.group(0)] ?? match.group(0)!;
12+
});
13+
}
14+
return pyDict;
15+
}

lib/codegen/dart/dio.dart

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,10 @@ import 'shared.dart';
88
class DartDioCodeGen {
99
String? getCode(
1010
RequestModel requestModel,
11-
String defaultUriScheme,
1211
) {
1312
try {
14-
String url = requestModel.url;
15-
if (!url.contains("://") && url.isNotEmpty) {
16-
url = "$defaultUriScheme://$url";
17-
}
1813
final next = generatedDartCode(
19-
url: url,
14+
url: requestModel.url,
2015
method: requestModel.method,
2116
queryParams: requestModel.enabledParamsMap,
2217
headers: requestModel.enabledHeadersMap,
@@ -60,12 +55,17 @@ class DartDioCodeGen {
6055
final List<Map<String,String>> formDataList = ${json.encode(formData)};
6156
for (var formField in formDataList) {
6257
if (formField['type'] == 'file') {
63-
formData.files.add(MapEntry(
64-
formField['name'],
65-
await MultipartFile.fromFile(formField['value'], filename: formField['value']),
58+
if (formField['value'] != null) {
59+
data.files.add(MapEntry(
60+
formField['name']!,
61+
await dio.MultipartFile.fromFile(formField['value']!,
62+
filename: formField['value']!),
6663
));
64+
}
6765
} else {
68-
formData.fields.add(MapEntry(formField['name'], formField['value']));
66+
if (formField['value'] != null) {
67+
data.fields.add(MapEntry(formField['name']!, formField['value']!));
68+
}
6969
}
7070
}
7171
''');
@@ -84,16 +84,16 @@ class DartDioCodeGen {
8484
dataExp = declareFinal('data').assign(strContent);
8585
// when add new type of [ContentType], need update [dataExp].
8686
case ContentType.formdata:
87-
dataExp = declareFinal('data').assign(refer('FormData()'));
87+
dataExp = declareFinal('data').assign(refer('dio.FormData()'));
8888
}
8989
}
9090
final responseExp = declareFinal('response').assign(InvokeExpression.newOf(
91-
refer('dio.Dio'),
91+
refer('dio.Dio()'),
9292
[literalString(url)],
9393
{
9494
if (queryParamExp != null) 'queryParameters': refer('queryParams'),
9595
if (headerExp != null)
96-
'options': refer('Options').newInstance(
96+
'options': refer('dio.Options').newInstance(
9797
[],
9898
{'headers': refer('headers')},
9999
),
@@ -117,7 +117,7 @@ class DartDioCodeGen {
117117
refer('print').call([refer('response').property('data')]),
118118
],
119119
onError: {
120-
'DioException': [
120+
'dio.DioException': [
121121
refer('print').call([
122122
refer('e').property('response').nullSafeProperty('statusCode'),
123123
]),

lib/codegen/dart/http.dart

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,10 @@ import 'shared.dart';
99
class DartHttpCodeGen {
1010
String? getCode(
1111
RequestModel requestModel,
12-
String defaultUriScheme,
1312
) {
1413
try {
15-
String url = requestModel.url;
16-
if (!url.contains("://") && url.isNotEmpty) {
17-
url = "$defaultUriScheme://$url";
18-
}
1914
final next = generatedDartCode(
20-
url: url,
15+
url: requestModel.url,
2116
method: requestModel.method,
2217
queryParams: requestModel.enabledParamsMap,
2318
headers: {...requestModel.enabledHeadersMap},
@@ -53,7 +48,9 @@ class DartHttpCodeGen {
5348
declareVar('uri').assign(refer('Uri.parse').call([literalString(url)]));
5449

5550
Expression? dataExp;
56-
if (kMethodsWithBody.contains(method) && (body?.isNotEmpty ?? false)) {
51+
if (kMethodsWithBody.contains(method) &&
52+
(body?.isNotEmpty ?? false) &&
53+
contentType != ContentType.formdata) {
5754
final strContent = CodeExpression(Code('r\'\'\'$body\'\'\''));
5855
dataExp = declareVar('body', type: refer('String')).assign(strContent);
5956
if (!hasContentTypeHeader) {
@@ -125,17 +122,29 @@ class DartHttpCodeGen {
125122

126123
final addHeaders = refer('request.headers.addAll').call([refer('headers')]);
127124
const multiPartList = Code('''
128-
for (Map<String, String> formData in formDataList){
129-
if (formData['type'] == 'text') {
130-
request.fields.addAll({formData['name']: formData['value']});
131-
} else {
132-
request.files.add(
133-
await http.MultipartFile.fromPath(
134-
formData['name'],
135-
formData['value'],
136-
),
137-
);
138-
}
125+
for (var formData in formDataList) {
126+
if (formData != null) {
127+
final name = formData['name'];
128+
final value = formData['value'];
129+
final type = formData['type'];
130+
131+
if (name != null && value != null && type != null) {
132+
if (type == 'text') {
133+
request.fields.addAll({name: value});
134+
} else {
135+
request.files.add(
136+
await http.MultipartFile.fromPath(
137+
name,
138+
value,
139+
),
140+
);
141+
}
142+
} else {
143+
print('Error: formData has null name, value, or type.');
144+
}
145+
} else {
146+
print('Error: formData is null.');
147+
}
139148
}
140149
''');
141150
var multiPartRequestSend =

0 commit comments

Comments
 (0)