@ohos-ports/curlconverter 4.12.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (270) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +153 -0
  3. package/dist/src/Headers.d.ts +23 -0
  4. package/dist/src/Headers.js +287 -0
  5. package/dist/src/Headers.js.map +1 -0
  6. package/dist/src/Query.d.ts +8 -0
  7. package/dist/src/Query.js +136 -0
  8. package/dist/src/Query.js.map +1 -0
  9. package/dist/src/Request.d.ts +200 -0
  10. package/dist/src/Request.js +1191 -0
  11. package/dist/src/Request.js.map +1 -0
  12. package/dist/src/Warnings.d.ts +15 -0
  13. package/dist/src/Warnings.js +111 -0
  14. package/dist/src/Warnings.js.map +1 -0
  15. package/dist/src/cli.d.ts +2 -0
  16. package/dist/src/cli.js +333 -0
  17. package/dist/src/cli.js.map +1 -0
  18. package/dist/src/curl/auth.d.ts +12 -0
  19. package/dist/src/curl/auth.js +40 -0
  20. package/dist/src/curl/auth.js.map +1 -0
  21. package/dist/src/curl/form.d.ts +28 -0
  22. package/dist/src/curl/form.js +218 -0
  23. package/dist/src/curl/form.js.map +1 -0
  24. package/dist/src/curl/opts.d.ts +2052 -0
  25. package/dist/src/curl/opts.js +1000 -0
  26. package/dist/src/curl/opts.js.map +1 -0
  27. package/dist/src/curl/url.d.ts +14 -0
  28. package/dist/src/curl/url.js +218 -0
  29. package/dist/src/curl/url.js.map +1 -0
  30. package/dist/src/generators/ansible.d.ts +5 -0
  31. package/dist/src/generators/ansible.js +282 -0
  32. package/dist/src/generators/ansible.js.map +1 -0
  33. package/dist/src/generators/c.d.ts +12 -0
  34. package/dist/src/generators/c.js +1230 -0
  35. package/dist/src/generators/c.js.map +1 -0
  36. package/dist/src/generators/cfml.d.ts +5 -0
  37. package/dist/src/generators/cfml.js +134 -0
  38. package/dist/src/generators/cfml.js.map +1 -0
  39. package/dist/src/generators/clojure.d.ts +7 -0
  40. package/dist/src/generators/clojure.js +436 -0
  41. package/dist/src/generators/clojure.js.map +1 -0
  42. package/dist/src/generators/csharp.d.ts +8 -0
  43. package/dist/src/generators/csharp.js +356 -0
  44. package/dist/src/generators/csharp.js.map +1 -0
  45. package/dist/src/generators/dart.d.ts +5 -0
  46. package/dist/src/generators/dart.js +273 -0
  47. package/dist/src/generators/dart.js.map +1 -0
  48. package/dist/src/generators/elixir.d.ts +8 -0
  49. package/dist/src/generators/elixir.js +296 -0
  50. package/dist/src/generators/elixir.js.map +1 -0
  51. package/dist/src/generators/go.d.ts +5 -0
  52. package/dist/src/generators/go.js +228 -0
  53. package/dist/src/generators/go.js.map +1 -0
  54. package/dist/src/generators/har.d.ts +7 -0
  55. package/dist/src/generators/har.js +115 -0
  56. package/dist/src/generators/har.js.map +1 -0
  57. package/dist/src/generators/http.d.ts +7 -0
  58. package/dist/src/generators/http.js +165 -0
  59. package/dist/src/generators/http.js.map +1 -0
  60. package/dist/src/generators/httpie.d.ts +5 -0
  61. package/dist/src/generators/httpie.js +446 -0
  62. package/dist/src/generators/httpie.js.map +1 -0
  63. package/dist/src/generators/java/httpurlconnection.d.ts +5 -0
  64. package/dist/src/generators/java/httpurlconnection.js +123 -0
  65. package/dist/src/generators/java/httpurlconnection.js.map +1 -0
  66. package/dist/src/generators/java/java.d.ts +8 -0
  67. package/dist/src/generators/java/java.js +247 -0
  68. package/dist/src/generators/java/java.js.map +1 -0
  69. package/dist/src/generators/java/jsoup.d.ts +5 -0
  70. package/dist/src/generators/java/jsoup.js +152 -0
  71. package/dist/src/generators/java/jsoup.js.map +1 -0
  72. package/dist/src/generators/java/okhttp.d.ts +5 -0
  73. package/dist/src/generators/java/okhttp.js +232 -0
  74. package/dist/src/generators/java/okhttp.js.map +1 -0
  75. package/dist/src/generators/javascript/axios.d.ts +5 -0
  76. package/dist/src/generators/javascript/axios.js +332 -0
  77. package/dist/src/generators/javascript/axios.js.map +1 -0
  78. package/dist/src/generators/javascript/got.d.ts +5 -0
  79. package/dist/src/generators/javascript/got.js +277 -0
  80. package/dist/src/generators/javascript/got.js.map +1 -0
  81. package/dist/src/generators/javascript/http.d.ts +8 -0
  82. package/dist/src/generators/javascript/http.js +183 -0
  83. package/dist/src/generators/javascript/http.js.map +1 -0
  84. package/dist/src/generators/javascript/javascript.d.ts +37 -0
  85. package/dist/src/generators/javascript/javascript.js +676 -0
  86. package/dist/src/generators/javascript/javascript.js.map +1 -0
  87. package/dist/src/generators/javascript/jquery.d.ts +15 -0
  88. package/dist/src/generators/javascript/jquery.js +297 -0
  89. package/dist/src/generators/javascript/jquery.js.map +1 -0
  90. package/dist/src/generators/javascript/ky.d.ts +7 -0
  91. package/dist/src/generators/javascript/ky.js +245 -0
  92. package/dist/src/generators/javascript/ky.js.map +1 -0
  93. package/dist/src/generators/javascript/request.d.ts +5 -0
  94. package/dist/src/generators/javascript/request.js +113 -0
  95. package/dist/src/generators/javascript/request.js.map +1 -0
  96. package/dist/src/generators/javascript/superagent.d.ts +10 -0
  97. package/dist/src/generators/javascript/superagent.js +301 -0
  98. package/dist/src/generators/javascript/superagent.js.map +1 -0
  99. package/dist/src/generators/javascript/xhr.d.ts +8 -0
  100. package/dist/src/generators/javascript/xhr.js +147 -0
  101. package/dist/src/generators/javascript/xhr.js.map +1 -0
  102. package/dist/src/generators/json.d.ts +45 -0
  103. package/dist/src/generators/json.js +197 -0
  104. package/dist/src/generators/json.js.map +1 -0
  105. package/dist/src/generators/julia.d.ts +8 -0
  106. package/dist/src/generators/julia.js +365 -0
  107. package/dist/src/generators/julia.js.map +1 -0
  108. package/dist/src/generators/kotlin.d.ts +8 -0
  109. package/dist/src/generators/kotlin.js +325 -0
  110. package/dist/src/generators/kotlin.js.map +1 -0
  111. package/dist/src/generators/lua.d.ts +5 -0
  112. package/dist/src/generators/lua.js +192 -0
  113. package/dist/src/generators/lua.js.map +1 -0
  114. package/dist/src/generators/matlab/common.d.ts +16 -0
  115. package/dist/src/generators/matlab/common.js +238 -0
  116. package/dist/src/generators/matlab/common.js.map +1 -0
  117. package/dist/src/generators/matlab/httpinterface.d.ts +2 -0
  118. package/dist/src/generators/matlab/httpinterface.js +211 -0
  119. package/dist/src/generators/matlab/httpinterface.js.map +1 -0
  120. package/dist/src/generators/matlab/matlab.d.ts +5 -0
  121. package/dist/src/generators/matlab/matlab.js +29 -0
  122. package/dist/src/generators/matlab/matlab.js.map +1 -0
  123. package/dist/src/generators/matlab/webservices.d.ts +2 -0
  124. package/dist/src/generators/matlab/webservices.js +191 -0
  125. package/dist/src/generators/matlab/webservices.js.map +1 -0
  126. package/dist/src/generators/objectivec.d.ts +8 -0
  127. package/dist/src/generators/objectivec.js +269 -0
  128. package/dist/src/generators/objectivec.js.map +1 -0
  129. package/dist/src/generators/ocaml.d.ts +8 -0
  130. package/dist/src/generators/ocaml.js +150 -0
  131. package/dist/src/generators/ocaml.js.map +1 -0
  132. package/dist/src/generators/perl.d.ts +9 -0
  133. package/dist/src/generators/perl.js +209 -0
  134. package/dist/src/generators/perl.js.map +1 -0
  135. package/dist/src/generators/php/guzzle.d.ts +5 -0
  136. package/dist/src/generators/php/guzzle.js +328 -0
  137. package/dist/src/generators/php/guzzle.js.map +1 -0
  138. package/dist/src/generators/php/php.d.ts +8 -0
  139. package/dist/src/generators/php/php.js +217 -0
  140. package/dist/src/generators/php/php.js.map +1 -0
  141. package/dist/src/generators/php/requests.d.ts +5 -0
  142. package/dist/src/generators/php/requests.js +89 -0
  143. package/dist/src/generators/php/requests.js.map +1 -0
  144. package/dist/src/generators/powershell.d.ts +11 -0
  145. package/dist/src/generators/powershell.js +377 -0
  146. package/dist/src/generators/powershell.js.map +1 -0
  147. package/dist/src/generators/python/http.d.ts +5 -0
  148. package/dist/src/generators/python/http.js +128 -0
  149. package/dist/src/generators/python/http.js.map +1 -0
  150. package/dist/src/generators/python/python.d.ts +22 -0
  151. package/dist/src/generators/python/python.js +1693 -0
  152. package/dist/src/generators/python/python.js.map +1 -0
  153. package/dist/src/generators/r/httr.d.ts +10 -0
  154. package/dist/src/generators/r/httr.js +298 -0
  155. package/dist/src/generators/r/httr.js.map +1 -0
  156. package/dist/src/generators/r/httr2.d.ts +5 -0
  157. package/dist/src/generators/r/httr2.js +214 -0
  158. package/dist/src/generators/r/httr2.js.map +1 -0
  159. package/dist/src/generators/ruby/httparty.d.ts +6 -0
  160. package/dist/src/generators/ruby/httparty.js +308 -0
  161. package/dist/src/generators/ruby/httparty.js.map +1 -0
  162. package/dist/src/generators/ruby/ruby.d.ts +14 -0
  163. package/dist/src/generators/ruby/ruby.js +515 -0
  164. package/dist/src/generators/ruby/ruby.js.map +1 -0
  165. package/dist/src/generators/rust.d.ts +8 -0
  166. package/dist/src/generators/rust.js +177 -0
  167. package/dist/src/generators/rust.js.map +1 -0
  168. package/dist/src/generators/swift.d.ts +8 -0
  169. package/dist/src/generators/swift.js +219 -0
  170. package/dist/src/generators/swift.js.map +1 -0
  171. package/dist/src/generators/wget.d.ts +8 -0
  172. package/dist/src/generators/wget.js +472 -0
  173. package/dist/src/generators/wget.js.map +1 -0
  174. package/dist/src/index.d.ts +53 -0
  175. package/dist/src/index.js +54 -0
  176. package/dist/src/index.js.map +1 -0
  177. package/dist/src/parse.d.ts +13 -0
  178. package/dist/src/parse.js +43 -0
  179. package/dist/src/parse.js.map +1 -0
  180. package/dist/src/shell/Parser.d.ts +4 -0
  181. package/dist/src/shell/Parser.js +6 -0
  182. package/dist/src/shell/Parser.js.map +1 -0
  183. package/dist/src/shell/Word.d.ts +48 -0
  184. package/dist/src/shell/Word.js +486 -0
  185. package/dist/src/shell/Word.js.map +1 -0
  186. package/dist/src/shell/tokenizer.d.ts +3 -0
  187. package/dist/src/shell/tokenizer.js +610 -0
  188. package/dist/src/shell/tokenizer.js.map +1 -0
  189. package/dist/src/shell/webParser.d.ts +4 -0
  190. package/dist/src/shell/webParser.js +15 -0
  191. package/dist/src/shell/webParser.js.map +1 -0
  192. package/dist/src/utils.d.ts +6 -0
  193. package/dist/src/utils.js +21 -0
  194. package/dist/src/utils.js.map +1 -0
  195. package/dist/tools/compare-requests.d.ts +2 -0
  196. package/dist/tools/compare-requests.js +448 -0
  197. package/dist/tools/compare-requests.js.map +1 -0
  198. package/dist/tools/gen-test.d.ts +2 -0
  199. package/dist/tools/gen-test.js +114 -0
  200. package/dist/tools/gen-test.js.map +1 -0
  201. package/dist/tree-sitter-bash.wasm +0 -0
  202. package/index.d.ts +3 -0
  203. package/package.json +97 -0
  204. package/src/Headers.ts +334 -0
  205. package/src/Query.ts +147 -0
  206. package/src/Request.ts +1649 -0
  207. package/src/Warnings.ts +154 -0
  208. package/src/cli.ts +561 -0
  209. package/src/curl/auth.ts +45 -0
  210. package/src/curl/form.ts +297 -0
  211. package/src/curl/opts.ts +1417 -0
  212. package/src/curl/url.ts +241 -0
  213. package/src/generators/ansible.ts +364 -0
  214. package/src/generators/c.ts +1371 -0
  215. package/src/generators/cfml.ts +155 -0
  216. package/src/generators/clojure.ts +521 -0
  217. package/src/generators/csharp.ts +383 -0
  218. package/src/generators/dart.ts +293 -0
  219. package/src/generators/elixir.ts +349 -0
  220. package/src/generators/go.ts +269 -0
  221. package/src/generators/har.ts +147 -0
  222. package/src/generators/http.ts +194 -0
  223. package/src/generators/httpie.ts +506 -0
  224. package/src/generators/java/httpurlconnection.ts +151 -0
  225. package/src/generators/java/java.ts +280 -0
  226. package/src/generators/java/jsoup.ts +172 -0
  227. package/src/generators/java/okhttp.ts +257 -0
  228. package/src/generators/javascript/axios.ts +395 -0
  229. package/src/generators/javascript/got.ts +362 -0
  230. package/src/generators/javascript/http.ts +232 -0
  231. package/src/generators/javascript/javascript.ts +825 -0
  232. package/src/generators/javascript/jquery.ts +360 -0
  233. package/src/generators/javascript/ky.ts +315 -0
  234. package/src/generators/javascript/request.ts +152 -0
  235. package/src/generators/javascript/superagent.ts +373 -0
  236. package/src/generators/javascript/xhr.ts +192 -0
  237. package/src/generators/json.ts +293 -0
  238. package/src/generators/julia.ts +398 -0
  239. package/src/generators/kotlin.ts +355 -0
  240. package/src/generators/lua.ts +209 -0
  241. package/src/generators/matlab/common.ts +281 -0
  242. package/src/generators/matlab/httpinterface.ts +284 -0
  243. package/src/generators/matlab/matlab.ts +39 -0
  244. package/src/generators/matlab/webservices.ts +263 -0
  245. package/src/generators/objectivec.ts +297 -0
  246. package/src/generators/ocaml.ts +168 -0
  247. package/src/generators/perl.ts +237 -0
  248. package/src/generators/php/guzzle.ts +368 -0
  249. package/src/generators/php/php.ts +239 -0
  250. package/src/generators/php/requests.ts +103 -0
  251. package/src/generators/powershell.ts +430 -0
  252. package/src/generators/python/http.ts +167 -0
  253. package/src/generators/python/python.ts +1934 -0
  254. package/src/generators/r/httr.ts +328 -0
  255. package/src/generators/r/httr2.ts +268 -0
  256. package/src/generators/ruby/httparty.ts +351 -0
  257. package/src/generators/ruby/ruby.ts +564 -0
  258. package/src/generators/rust.ts +243 -0
  259. package/src/generators/swift.ts +235 -0
  260. package/src/generators/wget.ts +533 -0
  261. package/src/index.ts +89 -0
  262. package/src/parse.ts +72 -0
  263. package/src/shell/Parser.ts +8 -0
  264. package/src/shell/Word.ts +531 -0
  265. package/src/shell/tokenizer.ts +736 -0
  266. package/src/shell/webParser.ts +18 -0
  267. package/src/utils.ts +25 -0
  268. package/tools/compare-requests.ts +571 -0
  269. package/tools/extract_curl_args.py +511 -0
  270. package/tools/gen-test.ts +129 -0
@@ -0,0 +1,18 @@
1
+ // This file replaces Parser.ts when curlconverter is running in the browser.
2
+
3
+ import Parser from "web-tree-sitter";
4
+
5
+ // NOTE: top-level await requires Safari 15+
6
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await#browser_compatibility
7
+ await Parser.init({
8
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
9
+ locateFile(scriptName: string, scriptDirectory: string) {
10
+ return "/" + scriptName;
11
+ },
12
+ });
13
+ const Bash = await Parser.Language.load("/tree-sitter-bash.wasm");
14
+ const parser = new Parser();
15
+ parser.setLanguage(Bash);
16
+
17
+ export default parser;
18
+ export type { Parser };
package/src/utils.ts ADDED
@@ -0,0 +1,25 @@
1
+ export class CCError extends Error {}
2
+
3
+ export const UTF8encoder = new TextEncoder();
4
+
5
+ // Note: !has() will lead to type errors
6
+ // TODO: replace with Object.hasOwn() once Node 16 is EOL'd on 2023-09-11
7
+ export function has<T, K extends PropertyKey>(
8
+ obj: T,
9
+ prop: K,
10
+ ): obj is T & Record<K, unknown> {
11
+ return Object.prototype.hasOwnProperty.call(obj, prop);
12
+ }
13
+
14
+ // Node.js 14 doesn't have btoa() and later Node.js versions deprecated it
15
+ export function btoa(str: string) {
16
+ if (typeof window === "undefined" || !window.btoa) {
17
+ return Buffer.from(str, "utf8").toString("base64");
18
+ } else {
19
+ return window.btoa(str);
20
+ }
21
+ }
22
+
23
+ export function isInt(s: string): boolean {
24
+ return /^\s*[+-]?\d+$/.test(s);
25
+ }
@@ -0,0 +1,571 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { exec } from "child_process";
4
+ import fs from "fs";
5
+ import net from "net";
6
+ import path from "path";
7
+ import { promisify } from "util";
8
+
9
+ import colors from "colors";
10
+ import { diffLines } from "diff";
11
+ import yargs from "yargs";
12
+ import { hideBin } from "yargs/helpers";
13
+
14
+ import { parse } from "../src/parse.js";
15
+ import { fixturesDir, converters } from "../test/test-utils.js";
16
+
17
+ const awaitableExec = promisify(exec);
18
+
19
+ const DEFAULT_PORT = 28139; // chosen randomly
20
+ const EXPECTED_URL = "localhost:" + DEFAULT_PORT;
21
+
22
+ const MINIMAL_HTTP_RESPONSE = `\
23
+ HTTP/1.1 200 OK
24
+ Content-Length: 12
25
+ Content-Type: text/plain; charset=utf-8
26
+
27
+ Hello World!`.replace(/\n/g, "\r\n");
28
+
29
+ const testDir = "/tmp/curlconverter"; // files are copied here to be executed
30
+ const executables = {
31
+ clojure: {
32
+ copy: "cp <file> /tmp/curlconverter/clojure/main.clj",
33
+ exec: 'cd /tmp/curlconverter/clojure && clj -Sdeps \'{:deps {clj-http/clj-http {:mvn/version "3.12.3"} cheshire/cheshire {:mvn/version "5.11.0"}}}\' -M main.clj',
34
+ },
35
+ csharp: {
36
+ setup:
37
+ "cd /tmp/curlconverter && dotnet new console -o csharp && sed -i '' 's/<ImplicitUsings>enable/<ImplicitUsings>disable/' /tmp/curlconverter/csharp/csharp.csproj",
38
+ copy: "cp <file> /tmp/curlconverter/csharp/Program.cs",
39
+ exec: "cd /tmp/curlconverter/csharp && dotnet run",
40
+ },
41
+ dart: {
42
+ setup:
43
+ "cd /tmp && mkdir -p curlconverter/dart && cd /tmp/curlconverter/dart && echo $'name:\\n dart\\nenvironment:\\n sdk: \">=2.14.0\"\\ndependencies:\\n http: any\\n' > pubspec.yaml && dart pub get",
44
+ copy: "cp <file> /tmp/curlconverter/dart/main.dart",
45
+ exec: "cd /tmp/curlconverter/dart && dart run main.dart",
46
+ },
47
+ elixir: {
48
+ setup:
49
+ "mix new /tmp/curlconverter/elixircurlconverter/ && sed -i '' 's/# {:dep_from_hexpm, \"~> 0.3.0\"}/{:httpoison, \"~> 1.8\"}/g' /tmp/curlconverter/elixirelixircurlconverter/mix.exs && cd /tmp/curlconverter/elixirelixircurlconverter/ && mix deps.get",
50
+ copy: "cp <file> /tmp/curlconverter/elixirelixircurlconverter/main.ex",
51
+ exec: "cd /tmp/curlconverter/elixirelixircurlconverter && mix run main.ex",
52
+ dir: "elixircurlconverter",
53
+ },
54
+ go: {
55
+ copy: "go build -o /tmp/curlconverter/go/go <file>",
56
+ exec: "cd /tmp/curlconverter/go && /tmp/curlconverter/go/go",
57
+ },
58
+ httpie: {
59
+ copy: function (contents: string) {
60
+ fs.writeFileSync(
61
+ "/tmp/curlconverter/httpie/main",
62
+ contents.trimEnd() + " --ignore-stdin" + "\n",
63
+ "utf8",
64
+ );
65
+ },
66
+ exec: "chmod +x /tmp/curlconverter/httpie/main && /tmp/curlconverter/httpie/main",
67
+ },
68
+ java: {
69
+ copy: function (contents: string) {
70
+ const [imports, ...rest] = contents.split("\n\n");
71
+
72
+ fs.writeFileSync(
73
+ "/tmp/curlconverter/java/Main.java",
74
+ imports +
75
+ "\n\n" +
76
+ "public class Main {\n" +
77
+ " public static void main(String[] args) throws Exception {\n" +
78
+ " " +
79
+ rest.join("\n\n") +
80
+ "\n" +
81
+ " }\n" +
82
+ "}\n",
83
+ "utf8",
84
+ );
85
+ },
86
+ exec: "cd /tmp/curlconverter/java && javac Main.java && java Main",
87
+ },
88
+ "java-httpurlconnection": {
89
+ copy: "cp <file> /tmp/curlconverter/java-httpurlconnection/Main.java",
90
+ exec: "cd /tmp/curlconverter/java-httpurlconnection && javac Main.java && java Main",
91
+ },
92
+ "java-jsoup": {
93
+ setup:
94
+ "if [ ! -d /tmp/curlconverter/java-jsoup ]; then echo setup java-jsoup by hand. && exit 1; fi",
95
+ // Like this:
96
+ // cd /tmp/curlconverter && mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=java-jsoup -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false
97
+ // cd java-jsoup
98
+ // then manually edit java-jsoup/pom.xml to fix the version of Java:
99
+
100
+ // <properties>
101
+ // <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
102
+ // <maven.compiler.source>18</maven.compiler.source>
103
+ // <maven.compiler.target>18</maven.compiler.target>
104
+ // </properties>
105
+
106
+ // and to install jsoup:
107
+
108
+ // <dependencies>
109
+ // <dependency>
110
+ // <groupId>org.jsoup</groupId>
111
+ // <artifactId>jsoup</artifactId>
112
+ // <version>1.16.1</version>
113
+ // </dependency>
114
+ // </dependencies>
115
+
116
+ // then install:
117
+ // mvn install
118
+
119
+ // setup: "cd /tmp/curlconverter && mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=java-jsoup -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false",
120
+ copy: function (contents: string) {
121
+ fs.writeFileSync(
122
+ "/tmp/curlconverter/java-jsoup/src/main/java/com/mycompany/app/Main.java",
123
+ `package com.mycompany.app;\n\n` +
124
+ contents.replace("class Main", "public class Main"),
125
+ "utf8",
126
+ );
127
+ },
128
+ exec: "cd /tmp/curlconverter/java-jsoup && mvn compile && mvn exec:java -Dexec.mainClass=com.mycompany.app.Main",
129
+ },
130
+ // mkdir -p /tmp/curlconverter/java-okhttp && cd /tmp/curlconverter/java-okhttp && curl https://repo1.maven.org/maven2/com/squareup/okhttp3/okhttp/4.11.0/okhttp-4.11.0.jar > okhttp-4.11.0.jar
131
+ // "java-okhttp": {
132
+ // setup: "mkdir -p /tmp/curlconverter/java-okhttp && cd /tmp/curlconverter/java-okhttp",
133
+ // copy: "cp <file> /tmp/curlconverter/java-okhttp/Main.java",
134
+ // exec: "cd /tmp/curlconverter/java-okhttp && javac -cp okhttp-4.11.0.jar Main.java && java Main",
135
+ // },
136
+ // javascript:
137
+ "javascript-jquery": {
138
+ setup:
139
+ "cd /tmp && mkdir -p curlconverter/javascript-jquery && cd curlconverter/javascript-jquery && npm init -y es6 && npm install jquery jsdom",
140
+ copy: function (contents: string) {
141
+ fs.writeFileSync(
142
+ "/tmp/curlconverter/javascript-jquery/main.js",
143
+ `import { JSDOM } from 'jsdom';
144
+ const { window } = new JSDOM();
145
+ import jQueryInit from 'jquery';
146
+ var $ = jQueryInit(window);
147
+
148
+ ` + contents,
149
+ "utf8",
150
+ );
151
+ },
152
+ exec: "cd /tmp/curlconverter/javascript-jquery && node main.js",
153
+ },
154
+ "javascript-xhr": {
155
+ setup:
156
+ "cd /tmp && mkdir -p curlconverter/javascript-xhr && cd curlconverter/javascript-xhr && npm init -y es6 && npm install xmlhttprequest",
157
+ copy: function (contents: string) {
158
+ fs.writeFileSync(
159
+ "/tmp/curlconverter/javascript-xhr/main.js",
160
+ "import { XMLHttpRequest } from 'xmlhttprequest';\n\n" + contents,
161
+ "utf8",
162
+ );
163
+ },
164
+ exec: "cd /tmp/curlconverter/javascript-xhr && node main.js",
165
+ },
166
+ julia: {
167
+ exec: "julia <file>",
168
+ },
169
+ kotlin: {
170
+ copy: function (contents: string) {
171
+ fs.writeFileSync(
172
+ "/tmp/curlconverter/kotlin/script.main.kts",
173
+ '@file:DependsOn("com.squareup.okhttp3:okhttp:4.11.0")\n\n' + contents,
174
+ "utf8",
175
+ );
176
+ },
177
+ exec: "cd /tmp/curlconverter/kotlin && kotlin script.main.kts",
178
+ },
179
+ lua: {
180
+ exec: "lua <file>",
181
+ },
182
+ node: {
183
+ setup:
184
+ "cd /tmp && mkdir -p curlconverter/node && cd curlconverter/node && npm init -y es6 && npm install node-fetch",
185
+ copy: "cp <file> /tmp/curlconverter/node/main.js",
186
+ exec: "cd /tmp/curlconverter/node && node main.js",
187
+ },
188
+ "node-axios": {
189
+ setup:
190
+ "cd /tmp && mkdir -p curlconverter/node-axios && cd curlconverter/node-axios && npm init -y es6 && npm install axios form-data",
191
+ copy: "cp <file> /tmp/curlconverter/node-axios/main.js",
192
+ exec: "cd /tmp/curlconverter/node-axios && node main.js",
193
+ },
194
+ "node-http": {
195
+ setup:
196
+ "cd /tmp && mkdir -p curlconverter/node-http && cd curlconverter/node-http && npm init -y es6 && npm install form-data",
197
+ copy: function (contents: string) {
198
+ fs.writeFileSync(
199
+ "/tmp/curlconverter/node-http/main.js",
200
+ contents.replace(
201
+ "hostname: 'localhost:28139',",
202
+ "hostname: 'localhost', port: 28139,",
203
+ ),
204
+ "utf8",
205
+ );
206
+ },
207
+ exec: "cd /tmp/curlconverter/node-http && node main.js",
208
+ },
209
+ "node-superagent": {
210
+ setup:
211
+ "cd /tmp && mkdir -p curlconverter/node-superagent && cd curlconverter/node-superagent && npm init -y es6 && npm install superagent",
212
+ copy: "cp <file> /tmp/curlconverter/node-superagent/main.js",
213
+ exec: "cd /tmp/curlconverter/node-superagent && node main.js",
214
+ },
215
+ objectivec: {
216
+ copy: function (contents: string) {
217
+ fs.writeFileSync(
218
+ "/tmp/curlconverter/objectivec/main.m",
219
+ contents
220
+ .replace(
221
+ "#import <Foundation/Foundation.h>\n",
222
+ "#import <Foundation/Foundation.h>\n" +
223
+ "\n" +
224
+ "int main(int argc, const char * argv[]) {\n" +
225
+ " @autoreleasepool {\n",
226
+ )
227
+ .replace(
228
+ "NSURLSession *session = ",
229
+ "\ndispatch_semaphore_t semaphore = dispatch_semaphore_create(0);\nNSURLSession *session = ",
230
+ )
231
+ .replace(
232
+ ' NSLog(@"%@", httpResponse);\n' + " }\n",
233
+ ' NSLog(@"%@", httpResponse);\n' +
234
+ " }\n" +
235
+ "dispatch_semaphore_signal(semaphore);\n",
236
+ ) +
237
+ "dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);\n" +
238
+ " }\n" +
239
+ " return 0;\n" +
240
+ "}\n",
241
+ "utf8",
242
+ );
243
+ },
244
+ exec: "cd /tmp/curlconverter/objectivec && clang -framework Foundation main.m -o main && ./main",
245
+ },
246
+ ocaml: {
247
+ copy: function (contents: string) {
248
+ fs.writeFileSync(
249
+ "/tmp/curlconverter/ocaml/main.ml",
250
+ contents
251
+ .replace(
252
+ "\nlet uri = Uri.of_string ",
253
+ "let body =\nlet uri = Uri.of_string ",
254
+ )
255
+ .replace(
256
+ " (* Do stuff with the result *)\n",
257
+ " body |> Cohttp_lwt.Body.to_string\n" +
258
+ "\n" +
259
+ "" +
260
+ "let () =\n" +
261
+ " let body = Lwt_main.run body in\n" +
262
+ " print_endline body\n",
263
+ ),
264
+ "utf8",
265
+ );
266
+ },
267
+ exec: "cd /tmp/curlconverter/ocaml && eval `opam config env` && ocamlbuild -use-ocamlfind -tag thread -pkg cohttp-lwt-unix main.native && ./main.native",
268
+ },
269
+ perl: {
270
+ exec: "perl <file>",
271
+ },
272
+ php: {
273
+ exec: "php <file>",
274
+ },
275
+ // php composer.phar global require guzzlehttp/guzzle:^7.0
276
+ "php-guzzle": {
277
+ setup:
278
+ "cd /tmp && mkdir -p curlconverter/php-guzzle && cd curlconverter/php-guzzle && php composer.phar require guzzlehttp/guzzle:^7.0",
279
+ copy: "cp <file> /tmp/curlconverter/php-guzzle/main.php",
280
+ exec: "cd /tmp/curlconverter/php-guzzle && php main.php",
281
+ },
282
+ powershell: {
283
+ copy: "cp <file> /tmp/curlconverter/powershell/main.ps1",
284
+ exec: "cd /tmp/curlconverter/powershell && pwsh main.ps1",
285
+ },
286
+ python: {
287
+ exec: "python3 <file>",
288
+ },
289
+ r: {
290
+ exec: "r < <file> --no-save",
291
+ },
292
+ "r-httr2": {
293
+ exec: "r < <file> --no-save",
294
+ },
295
+ ruby: {
296
+ exec: "ruby <file>",
297
+ },
298
+ "ruby-httparty": {
299
+ exec: "ruby <file>",
300
+ },
301
+ rust: {
302
+ setup:
303
+ "cd /tmp && cargo init --vcs none /tmp/curlconverter/rust && cd /tmp/curlconverter/rust && cargo add reqwest --features reqwest/blocking,reqwest/json",
304
+ copy: "cp <file> /tmp/curlconverter/rust/src/main.rs",
305
+ exec: "cd /tmp/curlconverter/rust && cargo run",
306
+ },
307
+ swift: {
308
+ copy: function (contents: string) {
309
+ fs.writeFileSync(
310
+ "/tmp/curlconverter/swift/main.swift",
311
+ contents
312
+ .replace(
313
+ "import Foundation\n",
314
+ "import Foundation\n\n// testing\nlet group = DispatchGroup()\ngroup.enter()\n",
315
+ )
316
+ .replace(
317
+ 'print(str ?? "")\n }\n',
318
+ 'print(str ?? "")\n }\n\n // testing\n group.leave()\n',
319
+ ) +
320
+ `
321
+ // testing
322
+ group.notify(queue: .main) {
323
+ exit(EXIT_SUCCESS) // Exit program when done
324
+ }
325
+ dispatchMain()\n`,
326
+
327
+ "utf8",
328
+ );
329
+ },
330
+ exec: "cd /tmp/curlconverter/swift && swift main.swift",
331
+ },
332
+ wget: {
333
+ exec: "bash <file>",
334
+ },
335
+ } as const;
336
+
337
+ const argv = await yargs(hideBin(process.argv))
338
+ .scriptName("compare-request")
339
+ .usage("Usage: $0 [--no-diff] [-l <language>] [test_name...]")
340
+ .option("diff", {
341
+ describe: "print a colorized diff instead of the raw requests",
342
+ default: true,
343
+ demandOption: false,
344
+ type: "boolean",
345
+ })
346
+ .option("sort", {
347
+ describe: "sort lines before comparing them",
348
+ default: false,
349
+ demandOption: false,
350
+ type: "boolean",
351
+ })
352
+ .option("l", {
353
+ alias: "language",
354
+ describe: "the language of the generated program to compare against",
355
+ choices: Object.keys(executables),
356
+ default: ["python"],
357
+ demandOption: false,
358
+ type: "string",
359
+ })
360
+ .alias("h", "help")
361
+ .help()
362
+ .parse();
363
+
364
+ const languages: (keyof typeof executables)[] = Array.isArray(argv.language)
365
+ ? argv.language
366
+ : [argv.language];
367
+
368
+ const testFile = async (
369
+ testFilename: string,
370
+ languages: (keyof typeof executables)[],
371
+ ): Promise<void> => {
372
+ const rawRequests: string[] = [];
373
+
374
+ // TODO: this is flaky
375
+ const server = net.createServer();
376
+ server.on("connection", (socket) => {
377
+ socket.setEncoding("utf8");
378
+
379
+ // Timeout very quickly because we only care about recieving the sent request.
380
+ socket.setTimeout(800, () => {
381
+ socket.end();
382
+ });
383
+
384
+ socket.on("data", (data) => {
385
+ // TODO: this is not a Buffer, it's a string...
386
+ rawRequests.push((data as unknown as string).replace(/\r\n/g, "\n"));
387
+
388
+ if (!socket.write(MINIMAL_HTTP_RESPONSE)) {
389
+ socket.pause();
390
+ }
391
+ });
392
+
393
+ socket.on("drain", () => {
394
+ socket.resume();
395
+ });
396
+ socket.on("timeout", () => {
397
+ socket.end();
398
+ });
399
+ socket.on("close", (error) => {
400
+ if (error) {
401
+ console.error("transmission error");
402
+ }
403
+ });
404
+ setTimeout(() => {
405
+ socket.destroy();
406
+ }, 1000);
407
+ });
408
+
409
+ server.maxConnections = 1;
410
+ server.listen(DEFAULT_PORT);
411
+ // setTimeout(function(){
412
+ // server.close();
413
+ // }, 5000);
414
+
415
+ const inputFile = path.join(
416
+ fixturesDir,
417
+ "curl_commands",
418
+ testFilename + ".sh",
419
+ );
420
+ if (!fs.existsSync(inputFile)) {
421
+ server.close();
422
+ throw new Error("input file doesn't exist: " + inputFile);
423
+ }
424
+ const curlCommand = fs.readFileSync(inputFile, "utf8");
425
+ const requestedUrl = parse(curlCommand)[0]
426
+ .urls[0].url.replace("http://", "")
427
+ .toString();
428
+ if (!requestedUrl.startsWith(EXPECTED_URL)) {
429
+ console.error("bad requested URL for " + testFilename);
430
+ console.error(" " + requestedUrl);
431
+ console.error("it needs to request");
432
+ console.error(" http://" + EXPECTED_URL);
433
+ console.error("so we can capture the data it sends.");
434
+ server.close();
435
+ return;
436
+ }
437
+ try {
438
+ await awaitableExec("bash " + inputFile);
439
+ } catch (e) {}
440
+
441
+ const files = languages.map((l: keyof typeof executables) =>
442
+ path.join(fixturesDir, l, testFilename + converters[l].extension),
443
+ );
444
+ for (let i = 0; i < languages.length; i++) {
445
+ const language = languages[i];
446
+ const languageFile = files[i];
447
+ const executable = executables[language];
448
+ if (fs.existsSync(languageFile)) {
449
+ if ("copy" in executable) {
450
+ if (typeof executable.copy === "function") {
451
+ executable.copy(fs.readFileSync(languageFile).toString());
452
+ } else {
453
+ await awaitableExec(executable.copy.replace("<file>", languageFile));
454
+ }
455
+ }
456
+ // TODO: escape?
457
+ const command = executable.exec.replace("<file>", languageFile);
458
+ try {
459
+ await awaitableExec(command);
460
+ } catch (e) {
461
+ // Uncomment for debugging. An error can happen because
462
+ // our server responds with a generic response.
463
+ console.error(e);
464
+ }
465
+ } else {
466
+ console.error(
467
+ language + " file doesn't exist, skipping: " + languageFile,
468
+ );
469
+ }
470
+ }
471
+
472
+ // TODO: allow ignoring headers for each converter
473
+ function sortLines(a: string): string {
474
+ return (
475
+ a
476
+ .split("\n")
477
+ .filter(Boolean)
478
+ .filter((s) => !s.toLowerCase().startsWith("user-agent: "))
479
+ .sort(Intl.Collator().compare)
480
+ .join("\n") + "\n"
481
+ );
482
+ }
483
+
484
+ const requestName = path.parse(inputFile).name;
485
+ console.log(requestName);
486
+ console.log("=".repeat(requestName.length));
487
+ console.log(fs.readFileSync(inputFile).toString());
488
+ for (const f of files) {
489
+ if (fs.existsSync(f)) {
490
+ console.log("=".repeat(requestName.length));
491
+ console.log(fs.readFileSync(f).toString());
492
+ }
493
+ }
494
+ console.log("=".repeat(requestName.length));
495
+
496
+ const [curlRequest, ...languageRequests] = rawRequests;
497
+ for (const languageRequest of languageRequests) {
498
+ if (argv.diff) {
499
+ const a = argv.sort ? sortLines(curlRequest) : curlRequest;
500
+ const b = argv.sort ? sortLines(languageRequest) : languageRequest;
501
+ for (const part of diffLines(a, b)) {
502
+ // green for additions, red for deletions
503
+ // grey for common parts
504
+ const color = part.added ? "green" : part.removed ? "red" : "grey";
505
+ process.stdout.write(colors[color](part.value));
506
+ }
507
+ } else {
508
+ console.log(curlRequest);
509
+ console.log(languageRequest);
510
+ }
511
+ }
512
+ console.log();
513
+
514
+ server.close();
515
+ };
516
+
517
+ // if no tests were specified, run them all
518
+ const tests = argv._;
519
+ if (!tests.length) {
520
+ const possibleTestFiles = fs
521
+ .readdirSync(path.join(fixturesDir, "curl_commands"))
522
+ .filter((n) => n.endsWith(".sh"));
523
+ for (const testFile of possibleTestFiles) {
524
+ for (const l of languages) {
525
+ if (
526
+ fs.existsSync(
527
+ path.join(
528
+ fixturesDir,
529
+ l,
530
+ testFile.replace(".sh", converters[l].extension),
531
+ ),
532
+ )
533
+ ) {
534
+ tests.push(testFile);
535
+ break;
536
+ }
537
+ }
538
+ }
539
+ if (!tests.length) {
540
+ console.error("no tests found");
541
+ process.exit(1);
542
+ }
543
+ }
544
+
545
+ // fs.rmSync(testDir, { recursive: true, force: true });
546
+ if (tests.length) {
547
+ for (const l of languages) {
548
+ const executable = executables[l];
549
+ let dir: string = l;
550
+ if ("dir" in executable) {
551
+ dir = executable.dir;
552
+ }
553
+ fs.mkdirSync(path.join(testDir, dir), { recursive: true });
554
+ if ("setup" in executable) {
555
+ console.error("running");
556
+ console.error(executable.setup);
557
+ await awaitableExec(executable.setup);
558
+ console.error();
559
+ }
560
+ }
561
+ }
562
+ function delay(ms: number) {
563
+ return new Promise((resolve) => setTimeout(resolve, ms));
564
+ }
565
+ for (const test of tests.sort()) {
566
+ const testName = path.parse(test.toString()).name;
567
+ await testFile(testName, languages);
568
+ await delay(1000);
569
+ }
570
+
571
+ process.exit(0);