@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.
- package/LICENSE +21 -0
- package/README.md +153 -0
- package/dist/src/Headers.d.ts +23 -0
- package/dist/src/Headers.js +287 -0
- package/dist/src/Headers.js.map +1 -0
- package/dist/src/Query.d.ts +8 -0
- package/dist/src/Query.js +136 -0
- package/dist/src/Query.js.map +1 -0
- package/dist/src/Request.d.ts +200 -0
- package/dist/src/Request.js +1191 -0
- package/dist/src/Request.js.map +1 -0
- package/dist/src/Warnings.d.ts +15 -0
- package/dist/src/Warnings.js +111 -0
- package/dist/src/Warnings.js.map +1 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +333 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/curl/auth.d.ts +12 -0
- package/dist/src/curl/auth.js +40 -0
- package/dist/src/curl/auth.js.map +1 -0
- package/dist/src/curl/form.d.ts +28 -0
- package/dist/src/curl/form.js +218 -0
- package/dist/src/curl/form.js.map +1 -0
- package/dist/src/curl/opts.d.ts +2052 -0
- package/dist/src/curl/opts.js +1000 -0
- package/dist/src/curl/opts.js.map +1 -0
- package/dist/src/curl/url.d.ts +14 -0
- package/dist/src/curl/url.js +218 -0
- package/dist/src/curl/url.js.map +1 -0
- package/dist/src/generators/ansible.d.ts +5 -0
- package/dist/src/generators/ansible.js +282 -0
- package/dist/src/generators/ansible.js.map +1 -0
- package/dist/src/generators/c.d.ts +12 -0
- package/dist/src/generators/c.js +1230 -0
- package/dist/src/generators/c.js.map +1 -0
- package/dist/src/generators/cfml.d.ts +5 -0
- package/dist/src/generators/cfml.js +134 -0
- package/dist/src/generators/cfml.js.map +1 -0
- package/dist/src/generators/clojure.d.ts +7 -0
- package/dist/src/generators/clojure.js +436 -0
- package/dist/src/generators/clojure.js.map +1 -0
- package/dist/src/generators/csharp.d.ts +8 -0
- package/dist/src/generators/csharp.js +356 -0
- package/dist/src/generators/csharp.js.map +1 -0
- package/dist/src/generators/dart.d.ts +5 -0
- package/dist/src/generators/dart.js +273 -0
- package/dist/src/generators/dart.js.map +1 -0
- package/dist/src/generators/elixir.d.ts +8 -0
- package/dist/src/generators/elixir.js +296 -0
- package/dist/src/generators/elixir.js.map +1 -0
- package/dist/src/generators/go.d.ts +5 -0
- package/dist/src/generators/go.js +228 -0
- package/dist/src/generators/go.js.map +1 -0
- package/dist/src/generators/har.d.ts +7 -0
- package/dist/src/generators/har.js +115 -0
- package/dist/src/generators/har.js.map +1 -0
- package/dist/src/generators/http.d.ts +7 -0
- package/dist/src/generators/http.js +165 -0
- package/dist/src/generators/http.js.map +1 -0
- package/dist/src/generators/httpie.d.ts +5 -0
- package/dist/src/generators/httpie.js +446 -0
- package/dist/src/generators/httpie.js.map +1 -0
- package/dist/src/generators/java/httpurlconnection.d.ts +5 -0
- package/dist/src/generators/java/httpurlconnection.js +123 -0
- package/dist/src/generators/java/httpurlconnection.js.map +1 -0
- package/dist/src/generators/java/java.d.ts +8 -0
- package/dist/src/generators/java/java.js +247 -0
- package/dist/src/generators/java/java.js.map +1 -0
- package/dist/src/generators/java/jsoup.d.ts +5 -0
- package/dist/src/generators/java/jsoup.js +152 -0
- package/dist/src/generators/java/jsoup.js.map +1 -0
- package/dist/src/generators/java/okhttp.d.ts +5 -0
- package/dist/src/generators/java/okhttp.js +232 -0
- package/dist/src/generators/java/okhttp.js.map +1 -0
- package/dist/src/generators/javascript/axios.d.ts +5 -0
- package/dist/src/generators/javascript/axios.js +332 -0
- package/dist/src/generators/javascript/axios.js.map +1 -0
- package/dist/src/generators/javascript/got.d.ts +5 -0
- package/dist/src/generators/javascript/got.js +277 -0
- package/dist/src/generators/javascript/got.js.map +1 -0
- package/dist/src/generators/javascript/http.d.ts +8 -0
- package/dist/src/generators/javascript/http.js +183 -0
- package/dist/src/generators/javascript/http.js.map +1 -0
- package/dist/src/generators/javascript/javascript.d.ts +37 -0
- package/dist/src/generators/javascript/javascript.js +676 -0
- package/dist/src/generators/javascript/javascript.js.map +1 -0
- package/dist/src/generators/javascript/jquery.d.ts +15 -0
- package/dist/src/generators/javascript/jquery.js +297 -0
- package/dist/src/generators/javascript/jquery.js.map +1 -0
- package/dist/src/generators/javascript/ky.d.ts +7 -0
- package/dist/src/generators/javascript/ky.js +245 -0
- package/dist/src/generators/javascript/ky.js.map +1 -0
- package/dist/src/generators/javascript/request.d.ts +5 -0
- package/dist/src/generators/javascript/request.js +113 -0
- package/dist/src/generators/javascript/request.js.map +1 -0
- package/dist/src/generators/javascript/superagent.d.ts +10 -0
- package/dist/src/generators/javascript/superagent.js +301 -0
- package/dist/src/generators/javascript/superagent.js.map +1 -0
- package/dist/src/generators/javascript/xhr.d.ts +8 -0
- package/dist/src/generators/javascript/xhr.js +147 -0
- package/dist/src/generators/javascript/xhr.js.map +1 -0
- package/dist/src/generators/json.d.ts +45 -0
- package/dist/src/generators/json.js +197 -0
- package/dist/src/generators/json.js.map +1 -0
- package/dist/src/generators/julia.d.ts +8 -0
- package/dist/src/generators/julia.js +365 -0
- package/dist/src/generators/julia.js.map +1 -0
- package/dist/src/generators/kotlin.d.ts +8 -0
- package/dist/src/generators/kotlin.js +325 -0
- package/dist/src/generators/kotlin.js.map +1 -0
- package/dist/src/generators/lua.d.ts +5 -0
- package/dist/src/generators/lua.js +192 -0
- package/dist/src/generators/lua.js.map +1 -0
- package/dist/src/generators/matlab/common.d.ts +16 -0
- package/dist/src/generators/matlab/common.js +238 -0
- package/dist/src/generators/matlab/common.js.map +1 -0
- package/dist/src/generators/matlab/httpinterface.d.ts +2 -0
- package/dist/src/generators/matlab/httpinterface.js +211 -0
- package/dist/src/generators/matlab/httpinterface.js.map +1 -0
- package/dist/src/generators/matlab/matlab.d.ts +5 -0
- package/dist/src/generators/matlab/matlab.js +29 -0
- package/dist/src/generators/matlab/matlab.js.map +1 -0
- package/dist/src/generators/matlab/webservices.d.ts +2 -0
- package/dist/src/generators/matlab/webservices.js +191 -0
- package/dist/src/generators/matlab/webservices.js.map +1 -0
- package/dist/src/generators/objectivec.d.ts +8 -0
- package/dist/src/generators/objectivec.js +269 -0
- package/dist/src/generators/objectivec.js.map +1 -0
- package/dist/src/generators/ocaml.d.ts +8 -0
- package/dist/src/generators/ocaml.js +150 -0
- package/dist/src/generators/ocaml.js.map +1 -0
- package/dist/src/generators/perl.d.ts +9 -0
- package/dist/src/generators/perl.js +209 -0
- package/dist/src/generators/perl.js.map +1 -0
- package/dist/src/generators/php/guzzle.d.ts +5 -0
- package/dist/src/generators/php/guzzle.js +328 -0
- package/dist/src/generators/php/guzzle.js.map +1 -0
- package/dist/src/generators/php/php.d.ts +8 -0
- package/dist/src/generators/php/php.js +217 -0
- package/dist/src/generators/php/php.js.map +1 -0
- package/dist/src/generators/php/requests.d.ts +5 -0
- package/dist/src/generators/php/requests.js +89 -0
- package/dist/src/generators/php/requests.js.map +1 -0
- package/dist/src/generators/powershell.d.ts +11 -0
- package/dist/src/generators/powershell.js +377 -0
- package/dist/src/generators/powershell.js.map +1 -0
- package/dist/src/generators/python/http.d.ts +5 -0
- package/dist/src/generators/python/http.js +128 -0
- package/dist/src/generators/python/http.js.map +1 -0
- package/dist/src/generators/python/python.d.ts +22 -0
- package/dist/src/generators/python/python.js +1693 -0
- package/dist/src/generators/python/python.js.map +1 -0
- package/dist/src/generators/r/httr.d.ts +10 -0
- package/dist/src/generators/r/httr.js +298 -0
- package/dist/src/generators/r/httr.js.map +1 -0
- package/dist/src/generators/r/httr2.d.ts +5 -0
- package/dist/src/generators/r/httr2.js +214 -0
- package/dist/src/generators/r/httr2.js.map +1 -0
- package/dist/src/generators/ruby/httparty.d.ts +6 -0
- package/dist/src/generators/ruby/httparty.js +308 -0
- package/dist/src/generators/ruby/httparty.js.map +1 -0
- package/dist/src/generators/ruby/ruby.d.ts +14 -0
- package/dist/src/generators/ruby/ruby.js +515 -0
- package/dist/src/generators/ruby/ruby.js.map +1 -0
- package/dist/src/generators/rust.d.ts +8 -0
- package/dist/src/generators/rust.js +177 -0
- package/dist/src/generators/rust.js.map +1 -0
- package/dist/src/generators/swift.d.ts +8 -0
- package/dist/src/generators/swift.js +219 -0
- package/dist/src/generators/swift.js.map +1 -0
- package/dist/src/generators/wget.d.ts +8 -0
- package/dist/src/generators/wget.js +472 -0
- package/dist/src/generators/wget.js.map +1 -0
- package/dist/src/index.d.ts +53 -0
- package/dist/src/index.js +54 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/parse.d.ts +13 -0
- package/dist/src/parse.js +43 -0
- package/dist/src/parse.js.map +1 -0
- package/dist/src/shell/Parser.d.ts +4 -0
- package/dist/src/shell/Parser.js +6 -0
- package/dist/src/shell/Parser.js.map +1 -0
- package/dist/src/shell/Word.d.ts +48 -0
- package/dist/src/shell/Word.js +486 -0
- package/dist/src/shell/Word.js.map +1 -0
- package/dist/src/shell/tokenizer.d.ts +3 -0
- package/dist/src/shell/tokenizer.js +610 -0
- package/dist/src/shell/tokenizer.js.map +1 -0
- package/dist/src/shell/webParser.d.ts +4 -0
- package/dist/src/shell/webParser.js +15 -0
- package/dist/src/shell/webParser.js.map +1 -0
- package/dist/src/utils.d.ts +6 -0
- package/dist/src/utils.js +21 -0
- package/dist/src/utils.js.map +1 -0
- package/dist/tools/compare-requests.d.ts +2 -0
- package/dist/tools/compare-requests.js +448 -0
- package/dist/tools/compare-requests.js.map +1 -0
- package/dist/tools/gen-test.d.ts +2 -0
- package/dist/tools/gen-test.js +114 -0
- package/dist/tools/gen-test.js.map +1 -0
- package/dist/tree-sitter-bash.wasm +0 -0
- package/index.d.ts +3 -0
- package/package.json +97 -0
- package/src/Headers.ts +334 -0
- package/src/Query.ts +147 -0
- package/src/Request.ts +1649 -0
- package/src/Warnings.ts +154 -0
- package/src/cli.ts +561 -0
- package/src/curl/auth.ts +45 -0
- package/src/curl/form.ts +297 -0
- package/src/curl/opts.ts +1417 -0
- package/src/curl/url.ts +241 -0
- package/src/generators/ansible.ts +364 -0
- package/src/generators/c.ts +1371 -0
- package/src/generators/cfml.ts +155 -0
- package/src/generators/clojure.ts +521 -0
- package/src/generators/csharp.ts +383 -0
- package/src/generators/dart.ts +293 -0
- package/src/generators/elixir.ts +349 -0
- package/src/generators/go.ts +269 -0
- package/src/generators/har.ts +147 -0
- package/src/generators/http.ts +194 -0
- package/src/generators/httpie.ts +506 -0
- package/src/generators/java/httpurlconnection.ts +151 -0
- package/src/generators/java/java.ts +280 -0
- package/src/generators/java/jsoup.ts +172 -0
- package/src/generators/java/okhttp.ts +257 -0
- package/src/generators/javascript/axios.ts +395 -0
- package/src/generators/javascript/got.ts +362 -0
- package/src/generators/javascript/http.ts +232 -0
- package/src/generators/javascript/javascript.ts +825 -0
- package/src/generators/javascript/jquery.ts +360 -0
- package/src/generators/javascript/ky.ts +315 -0
- package/src/generators/javascript/request.ts +152 -0
- package/src/generators/javascript/superagent.ts +373 -0
- package/src/generators/javascript/xhr.ts +192 -0
- package/src/generators/json.ts +293 -0
- package/src/generators/julia.ts +398 -0
- package/src/generators/kotlin.ts +355 -0
- package/src/generators/lua.ts +209 -0
- package/src/generators/matlab/common.ts +281 -0
- package/src/generators/matlab/httpinterface.ts +284 -0
- package/src/generators/matlab/matlab.ts +39 -0
- package/src/generators/matlab/webservices.ts +263 -0
- package/src/generators/objectivec.ts +297 -0
- package/src/generators/ocaml.ts +168 -0
- package/src/generators/perl.ts +237 -0
- package/src/generators/php/guzzle.ts +368 -0
- package/src/generators/php/php.ts +239 -0
- package/src/generators/php/requests.ts +103 -0
- package/src/generators/powershell.ts +430 -0
- package/src/generators/python/http.ts +167 -0
- package/src/generators/python/python.ts +1934 -0
- package/src/generators/r/httr.ts +328 -0
- package/src/generators/r/httr2.ts +268 -0
- package/src/generators/ruby/httparty.ts +351 -0
- package/src/generators/ruby/ruby.ts +564 -0
- package/src/generators/rust.ts +243 -0
- package/src/generators/swift.ts +235 -0
- package/src/generators/wget.ts +533 -0
- package/src/index.ts +89 -0
- package/src/parse.ts +72 -0
- package/src/shell/Parser.ts +8 -0
- package/src/shell/Word.ts +531 -0
- package/src/shell/tokenizer.ts +736 -0
- package/src/shell/webParser.ts +18 -0
- package/src/utils.ts +25 -0
- package/tools/compare-requests.ts +571 -0
- package/tools/extract_curl_args.py +511 -0
- package/tools/gen-test.ts +129 -0
package/src/Request.ts
ADDED
|
@@ -0,0 +1,1649 @@
|
|
|
1
|
+
import { Word, eq, mergeWords, joinWords } from "./shell/Word.js";
|
|
2
|
+
|
|
3
|
+
import { CCError, has, isInt } from "./utils.js";
|
|
4
|
+
import { warnf, warnIfPartsIgnored } from "./Warnings.js";
|
|
5
|
+
import type { Warnings, Support } from "./Warnings.js";
|
|
6
|
+
import type {
|
|
7
|
+
GlobalConfig,
|
|
8
|
+
OperationConfig,
|
|
9
|
+
SrcDataParam,
|
|
10
|
+
} from "./curl/opts.js";
|
|
11
|
+
|
|
12
|
+
import { Headers, parseCookies, parseCookiesStrict } from "./Headers.js";
|
|
13
|
+
import type { Cookies } from "./Headers.js";
|
|
14
|
+
|
|
15
|
+
import { pickAuth, type AuthType } from "./curl/auth.js";
|
|
16
|
+
export { AuthType } from "./curl/auth.js";
|
|
17
|
+
|
|
18
|
+
import { parseurl, type Curl_URL } from "./curl/url.js";
|
|
19
|
+
|
|
20
|
+
import { parseQueryString, percentEncodePlus } from "./Query.js";
|
|
21
|
+
import type { QueryList, QueryDict } from "./Query.js";
|
|
22
|
+
|
|
23
|
+
import { parseForm } from "./curl/form.js";
|
|
24
|
+
import type { FormParam } from "./curl/form.js";
|
|
25
|
+
|
|
26
|
+
export type FileParamType = "data" | "binary" | "urlencode" | "json";
|
|
27
|
+
export type DataType = FileParamType | "raw";
|
|
28
|
+
|
|
29
|
+
export type FileDataParam = {
|
|
30
|
+
filetype: FileParamType;
|
|
31
|
+
// The left side of "=" for --data-urlencode, can't be empty string
|
|
32
|
+
name?: Word;
|
|
33
|
+
filename: Word;
|
|
34
|
+
};
|
|
35
|
+
// "raw"-type SrcDataParams, and `FileParamType`s that read from stdin
|
|
36
|
+
// when we have its contents (because it comes from a pipe) are converted
|
|
37
|
+
// to plain strings
|
|
38
|
+
export type DataParam = Word | FileDataParam;
|
|
39
|
+
|
|
40
|
+
// struct getout
|
|
41
|
+
// https://github.com/curl/curl/blob/curl-7_86_0/src/tool_sdecls.h#L96
|
|
42
|
+
export interface RequestUrl {
|
|
43
|
+
// What it looked like in the input, used for error messages
|
|
44
|
+
originalUrl: Word;
|
|
45
|
+
|
|
46
|
+
url: Word;
|
|
47
|
+
// the query string can contain instructions to
|
|
48
|
+
// read the query string from a file, for example with
|
|
49
|
+
// --url-query @filename
|
|
50
|
+
// In that case we put "@filename" in the query string and "filename" here and
|
|
51
|
+
// warn the user that they'll need to modify the code to read that file.
|
|
52
|
+
queryReadsFile?: string;
|
|
53
|
+
|
|
54
|
+
urlObj: Curl_URL;
|
|
55
|
+
|
|
56
|
+
// If the ?query can't be losslessly parsed, then
|
|
57
|
+
// .urlWithoutQueryList === .url
|
|
58
|
+
// .queryList === undefined
|
|
59
|
+
urlWithoutQueryList: Word;
|
|
60
|
+
queryList?: QueryList;
|
|
61
|
+
// When all (if any) repeated keys in queryList happen one after the other
|
|
62
|
+
// ?a=1&a=1&b=2 (okay)
|
|
63
|
+
// ?a=1&b=2&a=1 (doesn't work, queryList is defined but queryDict isn't)
|
|
64
|
+
queryDict?: QueryDict;
|
|
65
|
+
|
|
66
|
+
urlWithoutQueryArray: Word;
|
|
67
|
+
urlWithOriginalQuery: Word;
|
|
68
|
+
// This includes the query in the URL and the query that comes from `--get --data` or `--url-query`
|
|
69
|
+
queryArray?: DataParam[];
|
|
70
|
+
// This is only the query in the URL
|
|
71
|
+
urlQueryArray?: DataParam[];
|
|
72
|
+
|
|
73
|
+
uploadFile?: Word;
|
|
74
|
+
output?: Word;
|
|
75
|
+
|
|
76
|
+
method: Word;
|
|
77
|
+
auth?: [Word, Word];
|
|
78
|
+
// TODO: should authType be per-url as well?
|
|
79
|
+
// authType?: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export type ProxyType =
|
|
83
|
+
| "http1"
|
|
84
|
+
| "http2"
|
|
85
|
+
| "socks4"
|
|
86
|
+
| "socks4a"
|
|
87
|
+
| "socks5"
|
|
88
|
+
| "socks5-hostname";
|
|
89
|
+
|
|
90
|
+
export interface Request {
|
|
91
|
+
// Will have at least one element (otherwise an error is raised)
|
|
92
|
+
urls: RequestUrl[];
|
|
93
|
+
globoff?: boolean;
|
|
94
|
+
disallowUsernameInUrl?: boolean;
|
|
95
|
+
pathAsIs?: boolean;
|
|
96
|
+
|
|
97
|
+
// Just the part that comes from `--get --data` or `--url-query` (not the query in the URL)
|
|
98
|
+
// unless there's only one URL, then it will include both.
|
|
99
|
+
queryArray?: DataParam[];
|
|
100
|
+
|
|
101
|
+
authType: AuthType;
|
|
102
|
+
proxyAuthType: AuthType;
|
|
103
|
+
awsSigV4?: Word;
|
|
104
|
+
oauth2Bearer?: Word;
|
|
105
|
+
delegation?: Word;
|
|
106
|
+
krb?: Word;
|
|
107
|
+
saslAuthzid?: Word;
|
|
108
|
+
saslIr?: boolean;
|
|
109
|
+
serviceName?: Word;
|
|
110
|
+
|
|
111
|
+
// A null header means the command explicitly disabled sending this header
|
|
112
|
+
headers: Headers;
|
|
113
|
+
proxyHeaders: Headers;
|
|
114
|
+
refererAuto?: boolean;
|
|
115
|
+
|
|
116
|
+
// .cookies is a parsed version of the Cookie header, if it can be parsed.
|
|
117
|
+
// Generators that use .cookies need to delete the header from .headers (usually).
|
|
118
|
+
cookies?: Cookies;
|
|
119
|
+
cookieFiles?: Word[];
|
|
120
|
+
cookieJar?: Word;
|
|
121
|
+
junkSessionCookies?: boolean;
|
|
122
|
+
|
|
123
|
+
compressed?: boolean;
|
|
124
|
+
transferEncoding?: boolean;
|
|
125
|
+
|
|
126
|
+
include?: boolean;
|
|
127
|
+
|
|
128
|
+
multipartUploads?: FormParam[];
|
|
129
|
+
// When multipartUploads comes from parsing a string in --data
|
|
130
|
+
// this can be set to true to say that sending the original data
|
|
131
|
+
// as a string would be more correct.
|
|
132
|
+
multipartUploadsDoesntRoundtrip?: boolean;
|
|
133
|
+
formEscape?: boolean;
|
|
134
|
+
|
|
135
|
+
dataArray?: DataParam[];
|
|
136
|
+
data?: Word;
|
|
137
|
+
dataReadsFile?: string;
|
|
138
|
+
isDataBinary?: boolean;
|
|
139
|
+
isDataRaw?: boolean;
|
|
140
|
+
|
|
141
|
+
ipv4?: boolean;
|
|
142
|
+
ipv6?: boolean;
|
|
143
|
+
|
|
144
|
+
proto?: Word;
|
|
145
|
+
protoRedir?: Word;
|
|
146
|
+
protoDefault?: Word;
|
|
147
|
+
|
|
148
|
+
tcpFastopen?: boolean;
|
|
149
|
+
|
|
150
|
+
localPort?: [Word, Word | null];
|
|
151
|
+
|
|
152
|
+
ignoreContentLength?: boolean;
|
|
153
|
+
|
|
154
|
+
interface?: Word;
|
|
155
|
+
|
|
156
|
+
ciphers?: Word;
|
|
157
|
+
curves?: Word;
|
|
158
|
+
insecure?: boolean;
|
|
159
|
+
certStatus?: boolean;
|
|
160
|
+
cert?: [Word, Word | null];
|
|
161
|
+
certType?: Word;
|
|
162
|
+
key?: Word;
|
|
163
|
+
keyType?: Word;
|
|
164
|
+
pass?: Word;
|
|
165
|
+
cacert?: Word;
|
|
166
|
+
caNative?: boolean;
|
|
167
|
+
sslAllowBeast?: boolean;
|
|
168
|
+
capath?: Word;
|
|
169
|
+
crlfile?: Word;
|
|
170
|
+
pinnedpubkey?: Word;
|
|
171
|
+
randomFile?: Word;
|
|
172
|
+
egdFile?: Word;
|
|
173
|
+
hsts?: Word[]; // a filename
|
|
174
|
+
alpn?: boolean;
|
|
175
|
+
|
|
176
|
+
tlsVersion?: "1" | "1.0" | "1.1" | "1.2" | "1.3";
|
|
177
|
+
tlsMax?: Word;
|
|
178
|
+
tls13Ciphers?: Word;
|
|
179
|
+
tlsauthtype?: Word;
|
|
180
|
+
tlspassword?: Word;
|
|
181
|
+
tlsuser?: Word;
|
|
182
|
+
sslAutoClientCert?: boolean;
|
|
183
|
+
sslNoRevoke?: boolean;
|
|
184
|
+
sslReqd?: boolean;
|
|
185
|
+
sslRevokeBestEffort?: boolean;
|
|
186
|
+
ssl?: boolean;
|
|
187
|
+
sslv2?: boolean;
|
|
188
|
+
sslv3?: boolean;
|
|
189
|
+
|
|
190
|
+
dohUrl?: Word;
|
|
191
|
+
dohInsecure?: boolean;
|
|
192
|
+
dohCertStatus?: boolean;
|
|
193
|
+
|
|
194
|
+
proxy?: Word;
|
|
195
|
+
proxyType?: ProxyType;
|
|
196
|
+
proxyAuth?: Word;
|
|
197
|
+
proxytunnel?: boolean;
|
|
198
|
+
noproxy?: Word; // a list of hosts or "*"
|
|
199
|
+
preproxy?: Word;
|
|
200
|
+
proxyAnyauth?: boolean;
|
|
201
|
+
proxyBasic?: boolean;
|
|
202
|
+
proxyCaNative?: boolean;
|
|
203
|
+
proxyCacert?: Word; // <file>
|
|
204
|
+
proxyCapath?: Word; // <dir>
|
|
205
|
+
proxyCertType?: Word; // <type>
|
|
206
|
+
proxyCert?: Word; // <cert[:passwd]>
|
|
207
|
+
proxyCiphers?: Word; // <list>
|
|
208
|
+
proxyCrlfile?: Word; // <file>
|
|
209
|
+
proxyDigest?: boolean;
|
|
210
|
+
proxyHttp2?: boolean;
|
|
211
|
+
proxyInsecure?: boolean;
|
|
212
|
+
proxyKeyType?: Word; // <type>
|
|
213
|
+
proxyKey?: Word; // <key>
|
|
214
|
+
proxyNegotiate?: boolean;
|
|
215
|
+
proxyNtlm?: boolean;
|
|
216
|
+
proxyPass?: Word; // <phrase>
|
|
217
|
+
proxyPinnedpubkey?: Word; // <hashes>
|
|
218
|
+
proxyServiceName?: Word; // <name>
|
|
219
|
+
proxySslAllowBeast?: boolean;
|
|
220
|
+
proxySslAutoClientCert?: boolean;
|
|
221
|
+
proxyTls13Ciphers?: Word; // <ciphersuite list>
|
|
222
|
+
proxyTlsauthtype?: Word; // <type>
|
|
223
|
+
proxyTlspassword?: Word; // <string>
|
|
224
|
+
proxyTlsuser?: Word; // <name>
|
|
225
|
+
proxyTlsv1?: boolean;
|
|
226
|
+
proxyUser?: Word; // <user:password>
|
|
227
|
+
proxy1?: boolean; // <host[:port]>
|
|
228
|
+
|
|
229
|
+
socks4?: Word;
|
|
230
|
+
socks4a?: Word;
|
|
231
|
+
socks5?: Word;
|
|
232
|
+
socks5Basic?: boolean;
|
|
233
|
+
socks5GssapiNec?: boolean;
|
|
234
|
+
socks5GssapiService?: Word;
|
|
235
|
+
socks5Gssapi?: boolean;
|
|
236
|
+
socks5Hostname?: Word;
|
|
237
|
+
|
|
238
|
+
haproxyClientIp?: Word;
|
|
239
|
+
haproxyProtocol?: boolean;
|
|
240
|
+
|
|
241
|
+
timeout?: Word; // a decimal, seconds
|
|
242
|
+
connectTimeout?: Word; // a decimal, seconds
|
|
243
|
+
expect100Timeout?: Word; // a decimal, seconds
|
|
244
|
+
happyEyeballsTimeoutMs?: Word; // an integer, milliseconds
|
|
245
|
+
speedLimit?: Word; // an integer
|
|
246
|
+
speedTime?: Word; // an integer
|
|
247
|
+
limitRate?: Word; // an integer with an optional unit
|
|
248
|
+
maxFilesize?: Word; // an intger with an optional unit
|
|
249
|
+
|
|
250
|
+
continueAt?: Word; // an integer or "-"
|
|
251
|
+
|
|
252
|
+
crlf?: boolean;
|
|
253
|
+
useAscii?: boolean;
|
|
254
|
+
|
|
255
|
+
remoteTime?: boolean;
|
|
256
|
+
|
|
257
|
+
clobber?: boolean;
|
|
258
|
+
|
|
259
|
+
ftpSkipPasvIp?: boolean;
|
|
260
|
+
|
|
261
|
+
fail?: boolean;
|
|
262
|
+
retry?: Word; // an integer, how many times to retry
|
|
263
|
+
retryMaxTime?: Word; // an integer, seconds
|
|
264
|
+
|
|
265
|
+
keepAlive?: boolean;
|
|
266
|
+
keepAliveTime?: Word; // an integer, seconds
|
|
267
|
+
|
|
268
|
+
altSvc?: Word;
|
|
269
|
+
|
|
270
|
+
followRedirects?: boolean;
|
|
271
|
+
followRedirectsTrusted?: boolean;
|
|
272
|
+
maxRedirects?: Word; // an integer
|
|
273
|
+
post301?: boolean;
|
|
274
|
+
post302?: boolean;
|
|
275
|
+
post303?: boolean;
|
|
276
|
+
|
|
277
|
+
httpVersion?: "1.0" | "1.1" | "2" | "2-prior-knowledge" | "3" | "3-only";
|
|
278
|
+
http0_9?: boolean;
|
|
279
|
+
http2?: boolean;
|
|
280
|
+
http3?: boolean;
|
|
281
|
+
|
|
282
|
+
stdin?: Word;
|
|
283
|
+
stdinFile?: Word;
|
|
284
|
+
|
|
285
|
+
resolve?: Word[]; // a list of host:port:address
|
|
286
|
+
connectTo?: Word[]; // a list of host:port:connect-to-host:connect-to-port
|
|
287
|
+
|
|
288
|
+
unixSocket?: Word;
|
|
289
|
+
abstractUnixSocket?: Word;
|
|
290
|
+
netrc?: "optional" | "required" | "ignored"; // undefined means implicitly "ignored"
|
|
291
|
+
netrcFile?: Word; // if undefined defaults to ~/.netrc
|
|
292
|
+
|
|
293
|
+
// Global options
|
|
294
|
+
verbose?: boolean;
|
|
295
|
+
silent?: boolean;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function buildURL(
|
|
299
|
+
global_: GlobalConfig,
|
|
300
|
+
config: OperationConfig,
|
|
301
|
+
url: Word,
|
|
302
|
+
uploadFile?: Word,
|
|
303
|
+
outputFile?: Word,
|
|
304
|
+
stdin?: Word,
|
|
305
|
+
stdinFile?: Word,
|
|
306
|
+
): RequestUrl {
|
|
307
|
+
const originalUrl = url;
|
|
308
|
+
const u = parseurl(global_, config, url);
|
|
309
|
+
|
|
310
|
+
// https://github.com/curl/curl/blob/curl-7_85_0/src/tool_operate.c#L1124
|
|
311
|
+
// https://github.com/curl/curl/blob/curl-7_85_0/src/tool_operhlp.c#L76
|
|
312
|
+
if (uploadFile) {
|
|
313
|
+
// TODO: it's more complicated
|
|
314
|
+
if (u.path.isEmpty()) {
|
|
315
|
+
u.path = uploadFile.prepend("/");
|
|
316
|
+
} else if (u.path.endsWith("/")) {
|
|
317
|
+
u.path = u.path.add(uploadFile);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (config.get) {
|
|
321
|
+
warnf(global_, [
|
|
322
|
+
"data-ignored",
|
|
323
|
+
"curl doesn't let you pass --get and --upload-file together",
|
|
324
|
+
]);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const urlWithOriginalQuery = mergeWords(
|
|
329
|
+
u.scheme,
|
|
330
|
+
"://",
|
|
331
|
+
u.host,
|
|
332
|
+
u.path,
|
|
333
|
+
u.query,
|
|
334
|
+
u.fragment,
|
|
335
|
+
);
|
|
336
|
+
|
|
337
|
+
// curl example.com example.com?foo=bar --url-query isshared=t
|
|
338
|
+
// will make requests for
|
|
339
|
+
// example.com/?isshared=t
|
|
340
|
+
// example.com/?foo=bar&isshared=t
|
|
341
|
+
//
|
|
342
|
+
// so the query could come from
|
|
343
|
+
// 1. `--url` (i.e. the requested URL)
|
|
344
|
+
// 2. `--url-query` or `--get --data` (the latter takes precedence)
|
|
345
|
+
//
|
|
346
|
+
// If it comes from the latter, we might need to generate code to read
|
|
347
|
+
// from one or more files.
|
|
348
|
+
// When there's multiple urls, the latter applies to all of them
|
|
349
|
+
// but the query from --url only applies to that URL.
|
|
350
|
+
//
|
|
351
|
+
// There's 3 cases for the query:
|
|
352
|
+
// 1. it's well-formed and can be expressed as a list of tuples (or a dict)
|
|
353
|
+
// `?one=1&one=1&two=2`
|
|
354
|
+
// 2. it can't, for example because one of the pieces doesn't have a '='
|
|
355
|
+
// `?one`
|
|
356
|
+
// 3. we need to generate code that reads from a file
|
|
357
|
+
//
|
|
358
|
+
// If there's only one URL we merge the query from the URL with the shared part.
|
|
359
|
+
//
|
|
360
|
+
// If there's multiple URLs and a shared part that reads from a file (case 3),
|
|
361
|
+
// we only write the file reading code once, pass it as the params= argument
|
|
362
|
+
// and the part from the URL has to be passed as a string in the URL
|
|
363
|
+
// and requests will combine the query in the URL with the query in params=.
|
|
364
|
+
//
|
|
365
|
+
// Otherwise, we print each query for each URL individually, either as a
|
|
366
|
+
// list of tuples if we can or in the URL if we can't.
|
|
367
|
+
//
|
|
368
|
+
// When files are passed in through --data-urlencode or --url-query
|
|
369
|
+
// we can usually treat them as case 1 as well (in Python), but that would
|
|
370
|
+
// generate code slightly different from curl because curl reads the file once
|
|
371
|
+
// upfront, whereas we would read the file multiple times and it might contain
|
|
372
|
+
// different data each time (for example if it's /dev/urandom).
|
|
373
|
+
let urlQueryArray: DataParam[] | null = null;
|
|
374
|
+
let queryArray: DataParam[] | null = null;
|
|
375
|
+
let queryStrReadsFile: string | null = null;
|
|
376
|
+
if (u.query.toBool() || (config["url-query"] && config["url-query"].length)) {
|
|
377
|
+
let queryStr: Word | null = null;
|
|
378
|
+
|
|
379
|
+
let queryParts: SrcDataParam[] = [];
|
|
380
|
+
if (u.query.toBool()) {
|
|
381
|
+
// remove the leading '?'
|
|
382
|
+
queryParts.push(["raw", u.query.slice(1)]);
|
|
383
|
+
[queryArray, queryStr, queryStrReadsFile] = buildData(
|
|
384
|
+
queryParts,
|
|
385
|
+
stdin,
|
|
386
|
+
stdinFile,
|
|
387
|
+
);
|
|
388
|
+
urlQueryArray = queryArray;
|
|
389
|
+
}
|
|
390
|
+
if (config["url-query"]) {
|
|
391
|
+
queryParts = queryParts.concat(config["url-query"]);
|
|
392
|
+
[queryArray, queryStr, queryStrReadsFile] = buildData(
|
|
393
|
+
queryParts,
|
|
394
|
+
stdin,
|
|
395
|
+
stdinFile,
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// TODO: check the curl source code
|
|
400
|
+
// TODO: curl localhost:8888/?
|
|
401
|
+
// will request /?
|
|
402
|
+
// but
|
|
403
|
+
// curl localhost:8888/? --url-query ''
|
|
404
|
+
// (or --get --data '') will request /
|
|
405
|
+
u.query = new Word();
|
|
406
|
+
if (queryStr && queryStr.toBool()) {
|
|
407
|
+
u.query = queryStr.prepend("?");
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
const urlWithoutQueryArray = mergeWords(
|
|
411
|
+
u.scheme,
|
|
412
|
+
"://",
|
|
413
|
+
u.host,
|
|
414
|
+
u.path,
|
|
415
|
+
u.fragment,
|
|
416
|
+
);
|
|
417
|
+
url = mergeWords(u.scheme, "://", u.host, u.path, u.query, u.fragment);
|
|
418
|
+
let urlWithoutQueryList = url;
|
|
419
|
+
// TODO: parseQueryString() doesn't accept leading '?'
|
|
420
|
+
let [queryList, queryDict] = parseQueryString(
|
|
421
|
+
u.query.toBool() ? u.query.slice(1) : new Word(),
|
|
422
|
+
);
|
|
423
|
+
if (queryList && queryList.length) {
|
|
424
|
+
// TODO: remove the fragment too?
|
|
425
|
+
urlWithoutQueryList = mergeWords(
|
|
426
|
+
u.scheme,
|
|
427
|
+
"://",
|
|
428
|
+
u.host,
|
|
429
|
+
u.path,
|
|
430
|
+
u.fragment,
|
|
431
|
+
);
|
|
432
|
+
} else {
|
|
433
|
+
queryList = null;
|
|
434
|
+
queryDict = null;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// TODO: --path-as-is
|
|
438
|
+
// TODO: --request-target
|
|
439
|
+
|
|
440
|
+
// curl expects you to uppercase methods always. If you do -X PoSt, that's what it
|
|
441
|
+
// will send, but most APIs will helpfully uppercase what you pass in as the method.
|
|
442
|
+
//
|
|
443
|
+
// There are many places where curl determines the method, this is the last one:
|
|
444
|
+
// https://github.com/curl/curl/blob/curl-7_85_0/lib/http.c#L2032
|
|
445
|
+
let method = new Word("GET");
|
|
446
|
+
if (
|
|
447
|
+
config.request &&
|
|
448
|
+
// Safari adds `-X null` if it can't determine the request type
|
|
449
|
+
// https://github.com/WebKit/WebKit/blob/f58ef38d48f42f5d7723691cb090823908ff5f9f/Source/WebInspectorUI/UserInterface/Models/Resource.js#L1250
|
|
450
|
+
!eq(config.request, "null")
|
|
451
|
+
) {
|
|
452
|
+
method = config.request;
|
|
453
|
+
} else if (config.head) {
|
|
454
|
+
method = new Word("HEAD");
|
|
455
|
+
} else if (uploadFile && uploadFile.toBool()) {
|
|
456
|
+
// --upload-file '' doesn't do anything.
|
|
457
|
+
method = new Word("PUT");
|
|
458
|
+
} else if (!config.get && (has(config, "data") || has(config, "form"))) {
|
|
459
|
+
method = new Word("POST");
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
const requestUrl: RequestUrl = {
|
|
463
|
+
originalUrl,
|
|
464
|
+
urlWithoutQueryList,
|
|
465
|
+
url,
|
|
466
|
+
urlObj: u,
|
|
467
|
+
urlWithOriginalQuery,
|
|
468
|
+
urlWithoutQueryArray,
|
|
469
|
+
method,
|
|
470
|
+
};
|
|
471
|
+
if (queryStrReadsFile) {
|
|
472
|
+
requestUrl.queryReadsFile = queryStrReadsFile;
|
|
473
|
+
}
|
|
474
|
+
if (queryList) {
|
|
475
|
+
requestUrl.queryList = queryList;
|
|
476
|
+
if (queryDict) {
|
|
477
|
+
requestUrl.queryDict = queryDict;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
if (queryArray) {
|
|
481
|
+
requestUrl.queryArray = queryArray;
|
|
482
|
+
}
|
|
483
|
+
if (urlQueryArray) {
|
|
484
|
+
requestUrl.urlQueryArray = urlQueryArray;
|
|
485
|
+
}
|
|
486
|
+
if (uploadFile) {
|
|
487
|
+
if (eq(uploadFile, "-") || eq(uploadFile, ".")) {
|
|
488
|
+
if (stdinFile) {
|
|
489
|
+
requestUrl.uploadFile = stdinFile;
|
|
490
|
+
} else if (stdin) {
|
|
491
|
+
warnf(global_, [
|
|
492
|
+
"upload-file-with-stdin-content",
|
|
493
|
+
"--upload-file with stdin content is not supported",
|
|
494
|
+
]);
|
|
495
|
+
requestUrl.uploadFile = uploadFile;
|
|
496
|
+
|
|
497
|
+
// TODO: this is complicated,
|
|
498
|
+
// --upload-file only applies per-URL so .data needs to become per-URL...
|
|
499
|
+
// if you pass --data and --upload-file or --get and --upload-file, curl will error
|
|
500
|
+
// if (config.url && config.url.length === 1) {
|
|
501
|
+
// config.data = [["raw", stdin]];
|
|
502
|
+
// } else {
|
|
503
|
+
// warnf(global_, [
|
|
504
|
+
// "upload-file-with-stdin-content-and-multiple-urls",
|
|
505
|
+
// "--upload-file with stdin content and multiple URLs is not supported",
|
|
506
|
+
// ]);
|
|
507
|
+
// }
|
|
508
|
+
} else {
|
|
509
|
+
requestUrl.uploadFile = uploadFile;
|
|
510
|
+
}
|
|
511
|
+
} else {
|
|
512
|
+
requestUrl.uploadFile = uploadFile;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
if (outputFile) {
|
|
516
|
+
// TODO: get stdout redirects of command
|
|
517
|
+
requestUrl.output = outputFile;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// --user takes precedence over the URL
|
|
521
|
+
const auth = config.user || u.auth;
|
|
522
|
+
if (auth) {
|
|
523
|
+
const [user, pass] = auth.split(":", 2);
|
|
524
|
+
requestUrl.auth = [user, pass || new Word()];
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
return requestUrl;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
function buildData(
|
|
531
|
+
configData: SrcDataParam[],
|
|
532
|
+
stdin?: Word,
|
|
533
|
+
stdinFile?: Word,
|
|
534
|
+
): [DataParam[], Word, string | null] {
|
|
535
|
+
const data: DataParam[] = [];
|
|
536
|
+
let dataStrState = new Word();
|
|
537
|
+
for (const [i, x] of configData.entries()) {
|
|
538
|
+
const type = x[0];
|
|
539
|
+
let value = x[1];
|
|
540
|
+
let name: Word | null = null;
|
|
541
|
+
|
|
542
|
+
if (i > 0 && type !== "json") {
|
|
543
|
+
dataStrState = dataStrState.append("&");
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
if (type === "urlencode") {
|
|
547
|
+
// curl checks for = before @
|
|
548
|
+
const splitOn = value.includes("=") || !value.includes("@") ? "=" : "@";
|
|
549
|
+
// If there's no = or @ then the entire content is treated as a value and encoded
|
|
550
|
+
if (value.includes("@") || value.includes("=")) {
|
|
551
|
+
[name, value] = value.split(splitOn, 2);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
if (splitOn === "=") {
|
|
555
|
+
if (name && name.toBool()) {
|
|
556
|
+
dataStrState = dataStrState.add(name).append("=");
|
|
557
|
+
}
|
|
558
|
+
// curl's --data-urlencode percent-encodes spaces as "+"
|
|
559
|
+
// https://github.com/curl/curl/blob/curl-7_86_0/src/tool_getparam.c#L630
|
|
560
|
+
dataStrState = dataStrState.add(percentEncodePlus(value));
|
|
561
|
+
continue;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
name = name && name.toBool() ? name : null;
|
|
565
|
+
value = value.prepend("@");
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
let filename: Word | null = null;
|
|
569
|
+
|
|
570
|
+
if (type !== "raw" && value.startsWith("@")) {
|
|
571
|
+
filename = value.slice(1);
|
|
572
|
+
if (eq(filename, "-")) {
|
|
573
|
+
if (stdin !== undefined) {
|
|
574
|
+
switch (type) {
|
|
575
|
+
case "binary":
|
|
576
|
+
case "json":
|
|
577
|
+
value = stdin;
|
|
578
|
+
break;
|
|
579
|
+
case "urlencode":
|
|
580
|
+
value = mergeWords(
|
|
581
|
+
name && name.length ? name.append("=") : new Word(),
|
|
582
|
+
percentEncodePlus(stdin),
|
|
583
|
+
);
|
|
584
|
+
break;
|
|
585
|
+
default:
|
|
586
|
+
value = stdin.replace(/[\n\r]/g, "");
|
|
587
|
+
}
|
|
588
|
+
filename = null;
|
|
589
|
+
} else if (stdinFile !== undefined) {
|
|
590
|
+
filename = stdinFile;
|
|
591
|
+
} else {
|
|
592
|
+
// TODO: if stdin is read twice, it will be empty the second time
|
|
593
|
+
// TODO: `STDIN_SENTINEL` so that we can tell the difference between
|
|
594
|
+
// a stdinFile called "-" and stdin for the error message
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
if (filename !== null) {
|
|
600
|
+
if (dataStrState.toBool()) {
|
|
601
|
+
data.push(dataStrState);
|
|
602
|
+
dataStrState = new Word();
|
|
603
|
+
}
|
|
604
|
+
const dataParam: DataParam = {
|
|
605
|
+
// If `filename` isn't null, then `type` can't be "raw"
|
|
606
|
+
filetype: type as FileParamType,
|
|
607
|
+
filename,
|
|
608
|
+
};
|
|
609
|
+
if (name) {
|
|
610
|
+
dataParam.name = name;
|
|
611
|
+
}
|
|
612
|
+
data.push(dataParam);
|
|
613
|
+
} else {
|
|
614
|
+
dataStrState = dataStrState.add(value);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
if (dataStrState.toBool()) {
|
|
618
|
+
data.push(dataStrState);
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
let dataStrReadsFile: string | null = null;
|
|
622
|
+
const dataStr = mergeWords(
|
|
623
|
+
...data.map((d) => {
|
|
624
|
+
if (!(d instanceof Word)) {
|
|
625
|
+
dataStrReadsFile ||= d.filename.toString(); // report first file
|
|
626
|
+
if (d.name) {
|
|
627
|
+
return mergeWords(d.name, "=@", d.filename);
|
|
628
|
+
}
|
|
629
|
+
return d.filename.prepend("@");
|
|
630
|
+
}
|
|
631
|
+
return d;
|
|
632
|
+
}),
|
|
633
|
+
);
|
|
634
|
+
|
|
635
|
+
return [data, dataStr, dataStrReadsFile];
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
// Parses a Content-Type header into a type and a list of parameters
|
|
639
|
+
function parseContentType(
|
|
640
|
+
string: string,
|
|
641
|
+
): [string, Array<[string, string]>] | null {
|
|
642
|
+
if (!string.includes(";")) {
|
|
643
|
+
return [string, []];
|
|
644
|
+
}
|
|
645
|
+
const semi = string.indexOf(";");
|
|
646
|
+
const type = string.slice(0, semi);
|
|
647
|
+
const rest = string.slice(semi);
|
|
648
|
+
|
|
649
|
+
// See https://www.w3.org/Protocols/rfc1341/4_Content-Type.html
|
|
650
|
+
// TODO: could be better, like reading to the next semicolon
|
|
651
|
+
const params = rest.match(
|
|
652
|
+
/;\s*([^;=]+)=(?:("[^"]*")|([^()<>@,;:\\"/[\]?.=]*))/g,
|
|
653
|
+
);
|
|
654
|
+
if (rest.trim() && !params) {
|
|
655
|
+
return null;
|
|
656
|
+
}
|
|
657
|
+
const parsedParams: Array<[string, string]> = [];
|
|
658
|
+
for (const param of params || []) {
|
|
659
|
+
const parsedParam = param.match(
|
|
660
|
+
/;\s*([^;=]+)=(?:("[^"]*")|([^()<>@,;:\\"/[\]?.=]*))/,
|
|
661
|
+
);
|
|
662
|
+
if (!parsedParam) {
|
|
663
|
+
return null;
|
|
664
|
+
}
|
|
665
|
+
const name = parsedParam[1];
|
|
666
|
+
const value = parsedParam[3] || parsedParam[2].slice(1, -1);
|
|
667
|
+
parsedParams.push([name, value]);
|
|
668
|
+
}
|
|
669
|
+
return [type, parsedParams];
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// Parses out the boundary= value from a Content-Type header
|
|
673
|
+
function parseBoundary(string: string): string | null {
|
|
674
|
+
const header = parseContentType(string);
|
|
675
|
+
if (!header) {
|
|
676
|
+
return null;
|
|
677
|
+
}
|
|
678
|
+
for (const [name, value] of header[1]) {
|
|
679
|
+
if (name === "boundary") {
|
|
680
|
+
return value;
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
return null;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
function parseRawForm(
|
|
687
|
+
data: string,
|
|
688
|
+
boundary: string,
|
|
689
|
+
): [FormParam[], boolean] | null {
|
|
690
|
+
const endBoundary = "\r\n--" + boundary + "--\r\n";
|
|
691
|
+
if (!data.endsWith(endBoundary)) {
|
|
692
|
+
return null;
|
|
693
|
+
}
|
|
694
|
+
data = data.slice(0, -endBoundary.length);
|
|
695
|
+
|
|
696
|
+
// TODO: if empty form should it be completely empty?
|
|
697
|
+
boundary = "--" + boundary + "\r\n";
|
|
698
|
+
if (data && !data.startsWith(boundary)) {
|
|
699
|
+
return null;
|
|
700
|
+
}
|
|
701
|
+
data = data.slice(boundary.length);
|
|
702
|
+
const parts = data.split("\r\n" + boundary);
|
|
703
|
+
const form: FormParam[] = [];
|
|
704
|
+
let roundtrips = true;
|
|
705
|
+
for (const part of parts) {
|
|
706
|
+
const lines = part.split("\r\n");
|
|
707
|
+
if (lines.length < 2) {
|
|
708
|
+
return null;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
const formParam: FormParam = {
|
|
712
|
+
name: new Word(),
|
|
713
|
+
content: new Word(),
|
|
714
|
+
};
|
|
715
|
+
let seenContentDisposition = false;
|
|
716
|
+
const headers: Word[] = [];
|
|
717
|
+
let i = 0;
|
|
718
|
+
for (; i < lines.length; i++) {
|
|
719
|
+
if (lines[i].length === 0) {
|
|
720
|
+
break;
|
|
721
|
+
}
|
|
722
|
+
const [name, value] = lines[i].split(": ", 2);
|
|
723
|
+
if (name === undefined || value === undefined) {
|
|
724
|
+
return null;
|
|
725
|
+
}
|
|
726
|
+
if (name.toLowerCase() === "content-disposition") {
|
|
727
|
+
if (seenContentDisposition) {
|
|
728
|
+
// should only have one
|
|
729
|
+
return null;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
const contentDisposition = parseContentType(value);
|
|
733
|
+
if (!contentDisposition) {
|
|
734
|
+
return null;
|
|
735
|
+
}
|
|
736
|
+
const [type, params] = contentDisposition;
|
|
737
|
+
if (type !== "form-data") {
|
|
738
|
+
return null;
|
|
739
|
+
}
|
|
740
|
+
let extra = 0;
|
|
741
|
+
for (const [paramName, paramValue] of params) {
|
|
742
|
+
switch (paramName) {
|
|
743
|
+
case "name":
|
|
744
|
+
formParam.name = new Word(paramValue);
|
|
745
|
+
break;
|
|
746
|
+
case "filename":
|
|
747
|
+
formParam.filename = new Word(paramValue);
|
|
748
|
+
break;
|
|
749
|
+
default:
|
|
750
|
+
extra++;
|
|
751
|
+
break;
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
if (extra) {
|
|
755
|
+
roundtrips = false;
|
|
756
|
+
// TODO: warn?
|
|
757
|
+
}
|
|
758
|
+
seenContentDisposition = true;
|
|
759
|
+
} else if (name.toLowerCase() === "content-type") {
|
|
760
|
+
formParam.contentType = new Word(value);
|
|
761
|
+
} else {
|
|
762
|
+
headers.push(new Word(lines[i]));
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
if (headers.length) {
|
|
766
|
+
formParam.headers = headers;
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
if (!seenContentDisposition) {
|
|
770
|
+
return null;
|
|
771
|
+
}
|
|
772
|
+
if (i === lines.length) {
|
|
773
|
+
return null;
|
|
774
|
+
}
|
|
775
|
+
if (formParam.name.isEmpty()) {
|
|
776
|
+
return null;
|
|
777
|
+
}
|
|
778
|
+
formParam.content = new Word(lines.slice(i + 1).join("\n"));
|
|
779
|
+
form.push(formParam);
|
|
780
|
+
}
|
|
781
|
+
return [form, roundtrips];
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
function buildRequest(
|
|
785
|
+
global_: GlobalConfig,
|
|
786
|
+
config: OperationConfig,
|
|
787
|
+
stdin?: Word,
|
|
788
|
+
stdinFile?: Word,
|
|
789
|
+
): Request {
|
|
790
|
+
if (!config.url || !config.url.length) {
|
|
791
|
+
// TODO: better error message (could be parsing fail)
|
|
792
|
+
throw new CCError("no URL specified!");
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
const headers = new Headers(config.header, global_.warnings);
|
|
796
|
+
const proxyHeaders = new Headers(
|
|
797
|
+
config["proxy-header"],
|
|
798
|
+
global_.warnings,
|
|
799
|
+
"--proxy-header",
|
|
800
|
+
);
|
|
801
|
+
|
|
802
|
+
let cookies;
|
|
803
|
+
const cookieFiles: Word[] = [];
|
|
804
|
+
const cookieHeader = headers.get("cookie");
|
|
805
|
+
if (cookieHeader) {
|
|
806
|
+
const parsedCookies = parseCookiesStrict(cookieHeader);
|
|
807
|
+
if (parsedCookies) {
|
|
808
|
+
cookies = parsedCookies;
|
|
809
|
+
}
|
|
810
|
+
} else if (cookieHeader === undefined && config.cookie) {
|
|
811
|
+
// If there is a Cookie header, --cookies is ignored
|
|
812
|
+
const cookieStrings: Word[] = [];
|
|
813
|
+
for (const c of config.cookie) {
|
|
814
|
+
// a --cookie without a = character reads from it as a filename
|
|
815
|
+
if (c.includes("=")) {
|
|
816
|
+
cookieStrings.push(c);
|
|
817
|
+
} else {
|
|
818
|
+
cookieFiles.push(c);
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
if (cookieStrings.length) {
|
|
822
|
+
const cookieString = joinWords(config.cookie, "; ");
|
|
823
|
+
headers.setIfMissing("Cookie", cookieString);
|
|
824
|
+
const parsedCookies = parseCookies(cookieString);
|
|
825
|
+
if (parsedCookies) {
|
|
826
|
+
cookies = parsedCookies;
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
let refererAuto = false;
|
|
832
|
+
if (config["user-agent"]) {
|
|
833
|
+
headers.setIfMissing("User-Agent", config["user-agent"]);
|
|
834
|
+
}
|
|
835
|
+
if (config.referer) {
|
|
836
|
+
if (config.referer.includes(";auto")) {
|
|
837
|
+
refererAuto = true;
|
|
838
|
+
}
|
|
839
|
+
// referer can be ";auto" or followed by ";auto", we ignore that.
|
|
840
|
+
const referer = config.referer.replace(/;auto$/, "");
|
|
841
|
+
if (referer.length) {
|
|
842
|
+
headers.setIfMissing("Referer", referer);
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
if (config.range) {
|
|
846
|
+
let range = config.range.prepend("bytes=");
|
|
847
|
+
if (!range.includes("-")) {
|
|
848
|
+
range = range.append("-");
|
|
849
|
+
}
|
|
850
|
+
headers.setIfMissing("Range", range);
|
|
851
|
+
}
|
|
852
|
+
if (config["time-cond"]) {
|
|
853
|
+
let timecond = config["time-cond"];
|
|
854
|
+
let header = "If-Modified-Since";
|
|
855
|
+
switch (timecond.charAt(0)) {
|
|
856
|
+
case "+":
|
|
857
|
+
timecond = timecond.slice(1);
|
|
858
|
+
break;
|
|
859
|
+
case "-":
|
|
860
|
+
timecond = timecond.slice(1);
|
|
861
|
+
header = "If-Unmodified-Since";
|
|
862
|
+
break;
|
|
863
|
+
case "=":
|
|
864
|
+
timecond = timecond.slice(1);
|
|
865
|
+
header = "Last-Modified";
|
|
866
|
+
break;
|
|
867
|
+
}
|
|
868
|
+
// TODO: parse date
|
|
869
|
+
headers.setIfMissing(header, timecond);
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
let data;
|
|
873
|
+
let dataStr;
|
|
874
|
+
let dataStrReadsFile;
|
|
875
|
+
let queryArray;
|
|
876
|
+
if (config.data && config.data.length) {
|
|
877
|
+
if (config.get) {
|
|
878
|
+
// https://github.com/curl/curl/blob/curl-7_85_0/src/tool_operate.c#L721
|
|
879
|
+
// --get --data will overwrite --url-query, but if there's no --data, for example,
|
|
880
|
+
// curl --url-query bar --get example.com
|
|
881
|
+
// it won't
|
|
882
|
+
// https://daniel.haxx.se/blog/2022/11/10/append-data-to-the-url-query/
|
|
883
|
+
config["url-query"] = config.data;
|
|
884
|
+
delete config.data;
|
|
885
|
+
} else {
|
|
886
|
+
[data, dataStr, dataStrReadsFile] = buildData(
|
|
887
|
+
config.data,
|
|
888
|
+
stdin,
|
|
889
|
+
stdinFile,
|
|
890
|
+
);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
if (config["url-query"]) {
|
|
894
|
+
[queryArray] = buildData(config["url-query"], stdin, stdinFile);
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
const urls: RequestUrl[] = [];
|
|
898
|
+
const uploadFiles = config["upload-file"] || [];
|
|
899
|
+
const outputFiles = config.output || [];
|
|
900
|
+
for (const [i, url] of config.url.entries()) {
|
|
901
|
+
urls.push(
|
|
902
|
+
buildURL(
|
|
903
|
+
global_,
|
|
904
|
+
config,
|
|
905
|
+
url,
|
|
906
|
+
uploadFiles[i],
|
|
907
|
+
outputFiles[i],
|
|
908
|
+
stdin,
|
|
909
|
+
stdinFile,
|
|
910
|
+
),
|
|
911
|
+
);
|
|
912
|
+
}
|
|
913
|
+
// --get moves --data into the URL's query string
|
|
914
|
+
if (config.get && config.data) {
|
|
915
|
+
delete config.data;
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
if ((config["upload-file"] || []).length > config.url.length) {
|
|
919
|
+
warnf(global_, [
|
|
920
|
+
"too-many-upload-files",
|
|
921
|
+
"Got more --upload-file/-T options than URLs: " +
|
|
922
|
+
config["upload-file"]
|
|
923
|
+
?.map((f) => JSON.stringify(f.toString()))
|
|
924
|
+
.join(", "),
|
|
925
|
+
]);
|
|
926
|
+
}
|
|
927
|
+
if ((config.output || []).length > config.url.length) {
|
|
928
|
+
warnf(global_, [
|
|
929
|
+
"too-many-output-files",
|
|
930
|
+
"Got more --output/-o options than URLs: " +
|
|
931
|
+
config.output?.map((f) => JSON.stringify(f.toString())).join(", "),
|
|
932
|
+
]);
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
const request: Request = {
|
|
936
|
+
urls,
|
|
937
|
+
authType: pickAuth(config.authtype),
|
|
938
|
+
proxyAuthType: pickAuth(config.proxyauthtype),
|
|
939
|
+
headers,
|
|
940
|
+
proxyHeaders,
|
|
941
|
+
};
|
|
942
|
+
// TODO: warn about unused stdin?
|
|
943
|
+
if (stdin) {
|
|
944
|
+
request.stdin = stdin;
|
|
945
|
+
}
|
|
946
|
+
if (stdinFile) {
|
|
947
|
+
request.stdinFile = stdinFile;
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
if (Object.prototype.hasOwnProperty.call(config, "globoff")) {
|
|
951
|
+
request.globoff = config.globoff;
|
|
952
|
+
}
|
|
953
|
+
if (
|
|
954
|
+
Object.prototype.hasOwnProperty.call(config, "disallow-username-in-url")
|
|
955
|
+
) {
|
|
956
|
+
request.disallowUsernameInUrl = config["disallow-username-in-url"];
|
|
957
|
+
}
|
|
958
|
+
if (Object.prototype.hasOwnProperty.call(config, "path-as-is")) {
|
|
959
|
+
request.pathAsIs = config["path-as-is"];
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
if (refererAuto) {
|
|
963
|
+
request.refererAuto = true;
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
if (cookies) {
|
|
967
|
+
// generators that use .cookies need to do
|
|
968
|
+
// deleteHeader(request, 'cookie')
|
|
969
|
+
request.cookies = cookies;
|
|
970
|
+
}
|
|
971
|
+
if (cookieFiles.length) {
|
|
972
|
+
request.cookieFiles = cookieFiles;
|
|
973
|
+
}
|
|
974
|
+
if (config["cookie-jar"]) {
|
|
975
|
+
request.cookieJar = config["cookie-jar"];
|
|
976
|
+
}
|
|
977
|
+
if (Object.prototype.hasOwnProperty.call(config, "junk-session-cookies")) {
|
|
978
|
+
request.junkSessionCookies = config["junk-session-cookies"];
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
if (Object.prototype.hasOwnProperty.call(config, "compressed")) {
|
|
982
|
+
request.compressed = config.compressed;
|
|
983
|
+
}
|
|
984
|
+
if (Object.prototype.hasOwnProperty.call(config, "tr-encoding")) {
|
|
985
|
+
request.transferEncoding = config["tr-encoding"];
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
if (config.include) {
|
|
989
|
+
request.include = true;
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
if (config.json) {
|
|
993
|
+
headers.setIfMissing("Content-Type", "application/json");
|
|
994
|
+
headers.setIfMissing("Accept", "application/json");
|
|
995
|
+
} else if (config.data) {
|
|
996
|
+
headers.setIfMissing("Content-Type", "application/x-www-form-urlencoded");
|
|
997
|
+
} else if (config.form) {
|
|
998
|
+
// TODO: warn when details (;filename=, etc.) are not supported
|
|
999
|
+
// by each converter.
|
|
1000
|
+
request.multipartUploads = parseForm(config.form, global_.warnings);
|
|
1001
|
+
//headers.setIfMissing("Content-Type", "multipart/form-data");
|
|
1002
|
+
}
|
|
1003
|
+
const contentType = headers.getContentType();
|
|
1004
|
+
const exactContentType = headers.get("Content-Type");
|
|
1005
|
+
if (
|
|
1006
|
+
config.data &&
|
|
1007
|
+
!dataStrReadsFile &&
|
|
1008
|
+
dataStr &&
|
|
1009
|
+
dataStr.isString() &&
|
|
1010
|
+
!config.form &&
|
|
1011
|
+
!request.multipartUploads &&
|
|
1012
|
+
contentType === "multipart/form-data" &&
|
|
1013
|
+
exactContentType &&
|
|
1014
|
+
exactContentType.isString()
|
|
1015
|
+
) {
|
|
1016
|
+
const boundary = parseBoundary(exactContentType.toString());
|
|
1017
|
+
if (boundary) {
|
|
1018
|
+
const form = parseRawForm(dataStr.toString(), boundary);
|
|
1019
|
+
if (form) {
|
|
1020
|
+
const [parsedForm, roundtrip] = form;
|
|
1021
|
+
request.multipartUploads = parsedForm;
|
|
1022
|
+
if (!roundtrip) {
|
|
1023
|
+
request.multipartUploadsDoesntRoundtrip = true;
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
if (Object.prototype.hasOwnProperty.call(config, "form-escape")) {
|
|
1030
|
+
request.formEscape = config["form-escape"];
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
if (config["aws-sigv4"]) {
|
|
1034
|
+
// https://github.com/curl/curl/blob/curl-7_86_0/lib/setopt.c#L678-L679
|
|
1035
|
+
request.authType = "aws-sigv4";
|
|
1036
|
+
request.awsSigV4 = config["aws-sigv4"];
|
|
1037
|
+
}
|
|
1038
|
+
if (request.authType === "bearer" && config["oauth2-bearer"]) {
|
|
1039
|
+
const bearer = config["oauth2-bearer"].prepend("Bearer ");
|
|
1040
|
+
headers.setIfMissing("Authorization", bearer);
|
|
1041
|
+
request.oauth2Bearer = config["oauth2-bearer"];
|
|
1042
|
+
}
|
|
1043
|
+
if (config.delegation) {
|
|
1044
|
+
request.delegation = config.delegation;
|
|
1045
|
+
}
|
|
1046
|
+
if (config.krb) {
|
|
1047
|
+
request.krb = config.krb;
|
|
1048
|
+
}
|
|
1049
|
+
if (config["sasl-authzid"]) {
|
|
1050
|
+
request.saslAuthzid = config["sasl-authzid"];
|
|
1051
|
+
}
|
|
1052
|
+
if (Object.prototype.hasOwnProperty.call(config, "sasl-ir")) {
|
|
1053
|
+
request.saslIr = config["sasl-ir"];
|
|
1054
|
+
}
|
|
1055
|
+
if (config.negotiate) {
|
|
1056
|
+
request.authType = "negotiate";
|
|
1057
|
+
}
|
|
1058
|
+
if (config["service-name"]) {
|
|
1059
|
+
request.serviceName = config["service-name"];
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
// TODO: ideally we should generate code that explicitly unsets the header too
|
|
1063
|
+
// no HTTP libraries allow that.
|
|
1064
|
+
headers.clearNulls();
|
|
1065
|
+
|
|
1066
|
+
if (config.data && config.data.length) {
|
|
1067
|
+
request.data = dataStr;
|
|
1068
|
+
if (dataStrReadsFile) {
|
|
1069
|
+
request.dataReadsFile = dataStrReadsFile;
|
|
1070
|
+
}
|
|
1071
|
+
request.dataArray = data;
|
|
1072
|
+
// TODO: remove these
|
|
1073
|
+
request.isDataRaw = false;
|
|
1074
|
+
request.isDataBinary = (data || []).some(
|
|
1075
|
+
(d) => !(d instanceof Word) && d.filetype === "binary",
|
|
1076
|
+
);
|
|
1077
|
+
}
|
|
1078
|
+
if (queryArray) {
|
|
1079
|
+
// If we have to generate code that reads from a file, we
|
|
1080
|
+
// need to do it once for all URLs.
|
|
1081
|
+
request.queryArray = queryArray;
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
if (Object.prototype.hasOwnProperty.call(config, "ipv4")) {
|
|
1085
|
+
request["ipv4"] = config["ipv4"];
|
|
1086
|
+
}
|
|
1087
|
+
if (Object.prototype.hasOwnProperty.call(config, "ipv6")) {
|
|
1088
|
+
request["ipv6"] = config["ipv6"];
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
if (config.proto) {
|
|
1092
|
+
// TODO: parse
|
|
1093
|
+
request.proto = config.proto;
|
|
1094
|
+
}
|
|
1095
|
+
if (config["proto-redir"]) {
|
|
1096
|
+
// TODO: parse
|
|
1097
|
+
request.protoRedir = config["proto-redir"];
|
|
1098
|
+
}
|
|
1099
|
+
if (config["proto-default"]) {
|
|
1100
|
+
request.protoDefault = config["proto-default"];
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
if (config["tcp-fastopen"]) {
|
|
1104
|
+
request.tcpFastopen = config["tcp-fastopen"];
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
if (config["local-port"]) {
|
|
1108
|
+
// TODO: check the range
|
|
1109
|
+
const [start, end] = config["local-port"].split("-", 1);
|
|
1110
|
+
if (end && end.toBool()) {
|
|
1111
|
+
request.localPort = [start, end];
|
|
1112
|
+
} else {
|
|
1113
|
+
request.localPort = [config["local-port"], null];
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
if (Object.prototype.hasOwnProperty.call(config, "ignore-content-length")) {
|
|
1118
|
+
request.ignoreContentLength = config["ignore-content-length"];
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
if (config.interface) {
|
|
1122
|
+
request.interface = config.interface;
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
if (config.ciphers) {
|
|
1126
|
+
request.ciphers = config.ciphers;
|
|
1127
|
+
}
|
|
1128
|
+
if (config.curves) {
|
|
1129
|
+
request.curves = config.curves;
|
|
1130
|
+
}
|
|
1131
|
+
if (config.insecure) {
|
|
1132
|
+
request.insecure = true;
|
|
1133
|
+
}
|
|
1134
|
+
if (Object.prototype.hasOwnProperty.call(config, "cert-status")) {
|
|
1135
|
+
request.certStatus = config["cert-status"];
|
|
1136
|
+
}
|
|
1137
|
+
// TODO: if the URL doesn't start with https://, curl doesn't verify
|
|
1138
|
+
// certificates, etc.
|
|
1139
|
+
if (config.cert) {
|
|
1140
|
+
if (config.cert.startsWith("pkcs11:") || !config.cert.match(/[:\\]/)) {
|
|
1141
|
+
request.cert = [config.cert, null];
|
|
1142
|
+
} else {
|
|
1143
|
+
// TODO: curl does more complex processing
|
|
1144
|
+
// find un-backslash-escaped colon, backslash might also be escaped with a backslash
|
|
1145
|
+
let colon = -1;
|
|
1146
|
+
|
|
1147
|
+
try {
|
|
1148
|
+
// Safari versions older than 16.4 don't support negative lookbehind
|
|
1149
|
+
colon = config.cert.search(/(?<!\\)(?:\\\\)*:/);
|
|
1150
|
+
} catch {
|
|
1151
|
+
colon = config.cert.search(/:/);
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
if (colon === -1) {
|
|
1155
|
+
request.cert = [config.cert, null];
|
|
1156
|
+
} else {
|
|
1157
|
+
const cert = config.cert.slice(0, colon);
|
|
1158
|
+
const password = config.cert.slice(colon + 1);
|
|
1159
|
+
if (password.toBool()) {
|
|
1160
|
+
request.cert = [cert, password];
|
|
1161
|
+
} else {
|
|
1162
|
+
request.cert = [cert, null];
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
if (config["cert-type"]) {
|
|
1168
|
+
const certType = config["cert-type"];
|
|
1169
|
+
request.certType = certType;
|
|
1170
|
+
|
|
1171
|
+
if (
|
|
1172
|
+
certType.isString() &&
|
|
1173
|
+
!["PEM", "DER", "ENG", "P12"].includes(certType.toString().toUpperCase())
|
|
1174
|
+
) {
|
|
1175
|
+
warnf(global_, [
|
|
1176
|
+
"cert-type-unknown",
|
|
1177
|
+
"not supported file type " +
|
|
1178
|
+
JSON.stringify(certType.toString()) +
|
|
1179
|
+
" for certificate",
|
|
1180
|
+
]);
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
if (config.key) {
|
|
1184
|
+
request.key = config.key;
|
|
1185
|
+
}
|
|
1186
|
+
if (config["key-type"]) {
|
|
1187
|
+
request.keyType = config["key-type"];
|
|
1188
|
+
}
|
|
1189
|
+
if (config.pass) {
|
|
1190
|
+
request.pass = config.pass;
|
|
1191
|
+
}
|
|
1192
|
+
if (config.cacert) {
|
|
1193
|
+
request.cacert = config.cacert;
|
|
1194
|
+
}
|
|
1195
|
+
if (Object.prototype.hasOwnProperty.call(config, "ca-native")) {
|
|
1196
|
+
request.caNative = config["ca-native"];
|
|
1197
|
+
}
|
|
1198
|
+
if (Object.prototype.hasOwnProperty.call(config, "ssl-allow-beast")) {
|
|
1199
|
+
request.sslAllowBeast = config["ssl-allow-beast"];
|
|
1200
|
+
}
|
|
1201
|
+
if (config.capath) {
|
|
1202
|
+
request.capath = config.capath;
|
|
1203
|
+
}
|
|
1204
|
+
if (config.crlfile) {
|
|
1205
|
+
request.crlfile = config.crlfile;
|
|
1206
|
+
}
|
|
1207
|
+
if (config.pinnedpubkey) {
|
|
1208
|
+
request.pinnedpubkey = config.pinnedpubkey;
|
|
1209
|
+
}
|
|
1210
|
+
if (config["random-file"]) {
|
|
1211
|
+
request.randomFile = config["random-file"];
|
|
1212
|
+
}
|
|
1213
|
+
if (config["egd-file"]) {
|
|
1214
|
+
request.egdFile = config["egd-file"];
|
|
1215
|
+
}
|
|
1216
|
+
if (config.hsts) {
|
|
1217
|
+
request.hsts = config.hsts;
|
|
1218
|
+
}
|
|
1219
|
+
if (Object.prototype.hasOwnProperty.call(config, "alpn")) {
|
|
1220
|
+
request.alpn = config.alpn;
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
if (config.tlsVersion) {
|
|
1224
|
+
request.tlsVersion = config.tlsVersion;
|
|
1225
|
+
}
|
|
1226
|
+
if (config["tls-max"]) {
|
|
1227
|
+
request.tlsMax = config["tls-max"];
|
|
1228
|
+
}
|
|
1229
|
+
if (config["tls13-ciphers"]) {
|
|
1230
|
+
request.tls13Ciphers = config["tls13-ciphers"];
|
|
1231
|
+
}
|
|
1232
|
+
if (config["tlsauthtype"]) {
|
|
1233
|
+
request.tlsauthtype = config["tlsauthtype"];
|
|
1234
|
+
}
|
|
1235
|
+
if (config["tlspassword"]) {
|
|
1236
|
+
request.tlspassword = config["tlspassword"];
|
|
1237
|
+
}
|
|
1238
|
+
if (config["tlsuser"]) {
|
|
1239
|
+
request.tlsuser = config["tlsuser"];
|
|
1240
|
+
}
|
|
1241
|
+
if (Object.prototype.hasOwnProperty.call(config, "ssl-allow-beast")) {
|
|
1242
|
+
request.sslAllowBeast = config["ssl-allow-beast"];
|
|
1243
|
+
}
|
|
1244
|
+
if (Object.prototype.hasOwnProperty.call(config, "ssl-auto-client-cert")) {
|
|
1245
|
+
request.sslAutoClientCert = config["ssl-auto-client-cert"];
|
|
1246
|
+
}
|
|
1247
|
+
if (Object.prototype.hasOwnProperty.call(config, "ssl-no-revoke")) {
|
|
1248
|
+
request.sslNoRevoke = config["ssl-no-revoke"];
|
|
1249
|
+
}
|
|
1250
|
+
if (Object.prototype.hasOwnProperty.call(config, "ssl-reqd")) {
|
|
1251
|
+
request.sslReqd = config["ssl-reqd"];
|
|
1252
|
+
}
|
|
1253
|
+
if (Object.prototype.hasOwnProperty.call(config, "ssl-revoke-best-effort")) {
|
|
1254
|
+
request.sslRevokeBestEffort = config["ssl-revoke-best-effort"];
|
|
1255
|
+
}
|
|
1256
|
+
if (Object.prototype.hasOwnProperty.call(config, "ssl")) {
|
|
1257
|
+
request.ssl = config["ssl"];
|
|
1258
|
+
}
|
|
1259
|
+
if (Object.prototype.hasOwnProperty.call(config, "sslv2")) {
|
|
1260
|
+
request.sslv2 = config["sslv2"];
|
|
1261
|
+
}
|
|
1262
|
+
if (Object.prototype.hasOwnProperty.call(config, "sslv3")) {
|
|
1263
|
+
request.sslv3 = config["sslv3"];
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
if (config["doh-url"]) {
|
|
1267
|
+
request.dohUrl = config["doh-url"];
|
|
1268
|
+
}
|
|
1269
|
+
if (Object.prototype.hasOwnProperty.call(config, "doh-insecure")) {
|
|
1270
|
+
request.dohInsecure = config["doh-insecure"];
|
|
1271
|
+
}
|
|
1272
|
+
if (Object.prototype.hasOwnProperty.call(config, "doh-cert-status")) {
|
|
1273
|
+
request.dohCertStatus = config["doh-cert-status"];
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
if (config.proxy) {
|
|
1277
|
+
// https://github.com/curl/curl/blob/e498a9b1fe5964a18eb2a3a99dc52160d2768261/lib/url.c#L2388-L2390
|
|
1278
|
+
request.proxy = config.proxy;
|
|
1279
|
+
if (request.proxyType && request.proxyType !== "http2") {
|
|
1280
|
+
delete request.proxyType;
|
|
1281
|
+
}
|
|
1282
|
+
if (config["proxy-user"]) {
|
|
1283
|
+
request.proxyAuth = config["proxy-user"];
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
if (Object.prototype.hasOwnProperty.call(config, "proxytunnel")) {
|
|
1287
|
+
request.proxytunnel = config.proxytunnel;
|
|
1288
|
+
}
|
|
1289
|
+
if (config.noproxy) {
|
|
1290
|
+
request.noproxy = config.noproxy;
|
|
1291
|
+
}
|
|
1292
|
+
if (config.preproxy) {
|
|
1293
|
+
request.preproxy = config.preproxy;
|
|
1294
|
+
}
|
|
1295
|
+
if (Object.prototype.hasOwnProperty.call(config, "proxy-anyauth")) {
|
|
1296
|
+
request.proxyAnyauth = config["proxy-anyauth"];
|
|
1297
|
+
}
|
|
1298
|
+
if (Object.prototype.hasOwnProperty.call(config, "proxy-basic")) {
|
|
1299
|
+
request.proxyBasic = config["proxy-basic"];
|
|
1300
|
+
}
|
|
1301
|
+
if (Object.prototype.hasOwnProperty.call(config, "proxy-digest")) {
|
|
1302
|
+
request.proxyDigest = config["proxy-digest"];
|
|
1303
|
+
}
|
|
1304
|
+
if (Object.prototype.hasOwnProperty.call(config, "proxy-negotiate")) {
|
|
1305
|
+
request.proxyNegotiate = config["proxy-negotiate"];
|
|
1306
|
+
}
|
|
1307
|
+
if (Object.prototype.hasOwnProperty.call(config, "proxy-ntlm")) {
|
|
1308
|
+
request.proxyNtlm = config["proxy-ntlm"];
|
|
1309
|
+
}
|
|
1310
|
+
if (Object.prototype.hasOwnProperty.call(config, "proxy-ca-native")) {
|
|
1311
|
+
request.proxyCaNative = config["proxy-ca-native"];
|
|
1312
|
+
}
|
|
1313
|
+
if (config["proxy-cacert"]) {
|
|
1314
|
+
request.proxyCacert = config["proxy-cacert"];
|
|
1315
|
+
}
|
|
1316
|
+
if (config["proxy-capath"]) {
|
|
1317
|
+
request.proxyCapath = config["proxy-capath"];
|
|
1318
|
+
}
|
|
1319
|
+
if (config["proxy-cert-type"]) {
|
|
1320
|
+
request.proxyCertType = config["proxy-cert-type"];
|
|
1321
|
+
}
|
|
1322
|
+
if (config["proxy-cert"]) {
|
|
1323
|
+
request.proxyCert = config["proxy-cert"];
|
|
1324
|
+
}
|
|
1325
|
+
if (config["proxy-ciphers"]) {
|
|
1326
|
+
request.proxyCiphers = config["proxy-ciphers"];
|
|
1327
|
+
}
|
|
1328
|
+
if (config["proxy-crlfile"]) {
|
|
1329
|
+
request.proxyCrlfile = config["proxy-crlfile"];
|
|
1330
|
+
}
|
|
1331
|
+
if (config["proxy-http2"]) {
|
|
1332
|
+
request.proxyType = "http2";
|
|
1333
|
+
}
|
|
1334
|
+
if (config["proxy1.0"]) {
|
|
1335
|
+
request.proxy = config["proxy1.0"];
|
|
1336
|
+
request.proxyType = "http1";
|
|
1337
|
+
}
|
|
1338
|
+
if (Object.prototype.hasOwnProperty.call(config, "proxy-insecure")) {
|
|
1339
|
+
request.proxyInsecure = config["proxy-insecure"];
|
|
1340
|
+
}
|
|
1341
|
+
if (config["proxy-key"]) {
|
|
1342
|
+
request.proxyKey = config["proxy-key"];
|
|
1343
|
+
}
|
|
1344
|
+
if (config["proxy-key-type"]) {
|
|
1345
|
+
request.proxyKeyType = config["proxy-key-type"];
|
|
1346
|
+
}
|
|
1347
|
+
if (config["proxy-pass"]) {
|
|
1348
|
+
request.proxyPass = config["proxy-pass"];
|
|
1349
|
+
}
|
|
1350
|
+
if (config["proxy-pinnedpubkey"]) {
|
|
1351
|
+
request.proxyPinnedpubkey = config["proxy-pinnedpubkey"];
|
|
1352
|
+
}
|
|
1353
|
+
if (config["proxy-pinnedpubkey"]) {
|
|
1354
|
+
request.proxyPinnedpubkey = config["proxy-pinnedpubkey"];
|
|
1355
|
+
}
|
|
1356
|
+
if (config["proxy-service-name"]) {
|
|
1357
|
+
request.proxyServiceName = config["proxy-service-name"];
|
|
1358
|
+
}
|
|
1359
|
+
if (Object.prototype.hasOwnProperty.call(config, "proxy-ssl-allow-beast")) {
|
|
1360
|
+
request.proxySslAllowBeast = config["proxy-ssl-allow-beast"];
|
|
1361
|
+
}
|
|
1362
|
+
if (
|
|
1363
|
+
Object.prototype.hasOwnProperty.call(config, "proxy-ssl-auto-client-cert")
|
|
1364
|
+
) {
|
|
1365
|
+
request.proxySslAutoClientCert = config["proxy-ssl-auto-client-cert"];
|
|
1366
|
+
}
|
|
1367
|
+
if (config["proxy-tls13-ciphers"]) {
|
|
1368
|
+
request.proxyTls13Ciphers = config["proxy-tls13-ciphers"];
|
|
1369
|
+
}
|
|
1370
|
+
if (config["proxy-tlsauthtype"]) {
|
|
1371
|
+
request.proxyTlsauthtype = config["proxy-tlsauthtype"];
|
|
1372
|
+
if (
|
|
1373
|
+
request.proxyTlsauthtype.isString() &&
|
|
1374
|
+
!eq(request.proxyTlsauthtype, "SRP")
|
|
1375
|
+
) {
|
|
1376
|
+
warnf(global_, [
|
|
1377
|
+
"proxy-tlsauthtype",
|
|
1378
|
+
"proxy-tlsauthtype is not supported: " + request.proxyTlsauthtype,
|
|
1379
|
+
]);
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
if (config["proxy-tlspassword"]) {
|
|
1383
|
+
request.proxyTlspassword = config["proxy-tlspassword"];
|
|
1384
|
+
}
|
|
1385
|
+
if (config["proxy-tlsuser"]) {
|
|
1386
|
+
request.proxyTlsuser = config["proxy-tlsuser"];
|
|
1387
|
+
}
|
|
1388
|
+
if (Object.prototype.hasOwnProperty.call(config, "proxy-tlsv1")) {
|
|
1389
|
+
request.proxyTlsv1 = config["proxy-tlsv1"];
|
|
1390
|
+
}
|
|
1391
|
+
if (config["proxy-user"]) {
|
|
1392
|
+
request.proxyUser = config["proxy-user"];
|
|
1393
|
+
}
|
|
1394
|
+
if (Object.prototype.hasOwnProperty.call(config, "proxytunnel")) {
|
|
1395
|
+
request.proxytunnel = config["proxytunnel"];
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
if (config["socks4"]) {
|
|
1399
|
+
request.proxy = config["socks4"];
|
|
1400
|
+
request.proxyType = "socks4";
|
|
1401
|
+
}
|
|
1402
|
+
if (config["socks4a"]) {
|
|
1403
|
+
request.proxy = config["socks4a"];
|
|
1404
|
+
request.proxyType = "socks4a";
|
|
1405
|
+
}
|
|
1406
|
+
if (config["socks5"]) {
|
|
1407
|
+
request.proxy = config["socks5"];
|
|
1408
|
+
request.proxyType = "socks5";
|
|
1409
|
+
}
|
|
1410
|
+
if (config["socks5-hostname"]) {
|
|
1411
|
+
request.proxy = config["socks5-hostname"];
|
|
1412
|
+
request.proxyType = "socks5-hostname";
|
|
1413
|
+
}
|
|
1414
|
+
if (Object.prototype.hasOwnProperty.call(config, "socks5-basic")) {
|
|
1415
|
+
request.socks5Basic = config["socks5-basic"];
|
|
1416
|
+
}
|
|
1417
|
+
if (Object.prototype.hasOwnProperty.call(config, "socks5-gssapi-nec")) {
|
|
1418
|
+
request.socks5GssapiNec = config["socks5-gssapi-nec"];
|
|
1419
|
+
}
|
|
1420
|
+
if (config["socks5-gssapi-service"]) {
|
|
1421
|
+
request.socks5GssapiService = config["socks5-gssapi-service"];
|
|
1422
|
+
}
|
|
1423
|
+
if (Object.prototype.hasOwnProperty.call(config, "socks5-gssapi")) {
|
|
1424
|
+
request.socks5Gssapi = config["socks5-gssapi"];
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
if (config["haproxy-clientip"]) {
|
|
1428
|
+
request.haproxyClientIp = config["haproxy-clientip"];
|
|
1429
|
+
}
|
|
1430
|
+
if (Object.prototype.hasOwnProperty.call(config, "haproxy-protocol")) {
|
|
1431
|
+
request.haproxyProtocol = config["haproxy-protocol"];
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
if (config["max-time"]) {
|
|
1435
|
+
request.timeout = config["max-time"];
|
|
1436
|
+
if (
|
|
1437
|
+
config["max-time"].isString() &&
|
|
1438
|
+
// TODO: parseFloat() like curl
|
|
1439
|
+
isNaN(parseFloat(config["max-time"].toString()))
|
|
1440
|
+
) {
|
|
1441
|
+
warnf(global_, [
|
|
1442
|
+
"max-time-not-number",
|
|
1443
|
+
"option --max-time: expected a proper numerical parameter: " +
|
|
1444
|
+
JSON.stringify(config["max-time"].toString()),
|
|
1445
|
+
]);
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
if (config["connect-timeout"]) {
|
|
1449
|
+
request.connectTimeout = config["connect-timeout"];
|
|
1450
|
+
if (
|
|
1451
|
+
config["connect-timeout"].isString() &&
|
|
1452
|
+
isNaN(parseFloat(config["connect-timeout"].toString()))
|
|
1453
|
+
) {
|
|
1454
|
+
warnf(global_, [
|
|
1455
|
+
"connect-timeout-not-number",
|
|
1456
|
+
"option --connect-timeout: expected a proper numerical parameter: " +
|
|
1457
|
+
JSON.stringify(config["connect-timeout"].toString()),
|
|
1458
|
+
]);
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
if (config["expect100-timeout"]) {
|
|
1462
|
+
request.expect100Timeout = config["expect100-timeout"];
|
|
1463
|
+
if (
|
|
1464
|
+
config["expect100-timeout"].isString() &&
|
|
1465
|
+
isNaN(parseFloat(config["expect100-timeout"].toString()))
|
|
1466
|
+
) {
|
|
1467
|
+
warnf(global_, [
|
|
1468
|
+
"expect100-timeout-not-number",
|
|
1469
|
+
"option --expect100-timeout: expected a proper numerical parameter: " +
|
|
1470
|
+
JSON.stringify(config["expect100-timeout"].toString()),
|
|
1471
|
+
]);
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
if (config["happy-eyeballs-timeout-ms"]) {
|
|
1475
|
+
request.happyEyeballsTimeoutMs = config["happy-eyeballs-timeout-ms"];
|
|
1476
|
+
}
|
|
1477
|
+
if (config["speed-limit"]) {
|
|
1478
|
+
request.speedLimit = config["speed-limit"];
|
|
1479
|
+
}
|
|
1480
|
+
if (config["speed-time"]) {
|
|
1481
|
+
request.speedTime = config["speed-time"];
|
|
1482
|
+
}
|
|
1483
|
+
if (config["limit-rate"]) {
|
|
1484
|
+
request.limitRate = config["limit-rate"];
|
|
1485
|
+
}
|
|
1486
|
+
if (config["max-filesize"]) {
|
|
1487
|
+
request.maxFilesize = config["max-filesize"];
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
if (Object.prototype.hasOwnProperty.call(config, "keepalive")) {
|
|
1491
|
+
request.keepAlive = config.keepalive;
|
|
1492
|
+
}
|
|
1493
|
+
if (config["keepalive-time"]) {
|
|
1494
|
+
request.keepAliveTime = config["keepalive-time"];
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1497
|
+
if (config["alt-svc"]) {
|
|
1498
|
+
request.altSvc = config["alt-svc"];
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
if (Object.prototype.hasOwnProperty.call(config, "location")) {
|
|
1502
|
+
request.followRedirects = config.location;
|
|
1503
|
+
}
|
|
1504
|
+
if (config["location-trusted"]) {
|
|
1505
|
+
request.followRedirectsTrusted = config["location-trusted"];
|
|
1506
|
+
}
|
|
1507
|
+
if (config["max-redirs"]) {
|
|
1508
|
+
request.maxRedirects = config["max-redirs"].trim();
|
|
1509
|
+
if (
|
|
1510
|
+
config["max-redirs"].isString() &&
|
|
1511
|
+
!isInt(config["max-redirs"].toString())
|
|
1512
|
+
) {
|
|
1513
|
+
warnf(global_, [
|
|
1514
|
+
"max-redirs-not-int",
|
|
1515
|
+
"option --max-redirs: expected a proper numerical parameter: " +
|
|
1516
|
+
JSON.stringify(config["max-redirs"].toString()),
|
|
1517
|
+
]);
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
if (Object.prototype.hasOwnProperty.call(config, "post301")) {
|
|
1521
|
+
request.post301 = config.post301;
|
|
1522
|
+
}
|
|
1523
|
+
if (Object.prototype.hasOwnProperty.call(config, "post302")) {
|
|
1524
|
+
request.post302 = config.post302;
|
|
1525
|
+
}
|
|
1526
|
+
if (Object.prototype.hasOwnProperty.call(config, "post303")) {
|
|
1527
|
+
request.post303 = config.post303;
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
if (config.fail) {
|
|
1531
|
+
request.fail = config.fail;
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
if (config.retry) {
|
|
1535
|
+
request.retry = config.retry;
|
|
1536
|
+
}
|
|
1537
|
+
if (config["retry-max-time"]) {
|
|
1538
|
+
request.retryMaxTime = config["retry-max-time"];
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
if (Object.prototype.hasOwnProperty.call(config, "ftp-skip-pasv-ip")) {
|
|
1542
|
+
request.ftpSkipPasvIp = config["ftp-skip-pasv-ip"];
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
if (config.httpVersion) {
|
|
1546
|
+
if (
|
|
1547
|
+
config.httpVersion === "2" ||
|
|
1548
|
+
config.httpVersion === "2-prior-knowledge"
|
|
1549
|
+
) {
|
|
1550
|
+
request.http2 = true;
|
|
1551
|
+
}
|
|
1552
|
+
if (config.httpVersion === "3" || config.httpVersion === "3-only") {
|
|
1553
|
+
request.http3 = true;
|
|
1554
|
+
}
|
|
1555
|
+
request.httpVersion = config.httpVersion;
|
|
1556
|
+
}
|
|
1557
|
+
if (Object.prototype.hasOwnProperty.call(config, "http0.9")) {
|
|
1558
|
+
request.http0_9 = config["http0.9"];
|
|
1559
|
+
}
|
|
1560
|
+
|
|
1561
|
+
if (config.resolve && config.resolve.length) {
|
|
1562
|
+
request.resolve = config.resolve;
|
|
1563
|
+
}
|
|
1564
|
+
if (config["connect-to"] && config["connect-to"].length) {
|
|
1565
|
+
request.connectTo = config["connect-to"];
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
if (config["unix-socket"]) {
|
|
1569
|
+
request.unixSocket = config["unix-socket"];
|
|
1570
|
+
}
|
|
1571
|
+
if (config["abstract-unix-socket"]) {
|
|
1572
|
+
request.abstractUnixSocket = config["abstract-unix-socket"];
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
if (config["netrc-optional"]) {
|
|
1576
|
+
request.netrc = "optional";
|
|
1577
|
+
} else if (config.netrc || config["netrc-file"]) {
|
|
1578
|
+
request.netrc = "required";
|
|
1579
|
+
} else if (config.netrc === false) {
|
|
1580
|
+
// TODO || config["netrc-optional"] === false ?
|
|
1581
|
+
request.netrc = "ignored";
|
|
1582
|
+
}
|
|
1583
|
+
if (config["netrc-file"]) {
|
|
1584
|
+
request.netrcFile = config["netrc-file"];
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
if (config["use-ascii"]) {
|
|
1588
|
+
request.useAscii = config["use-ascii"];
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
if (config["continue-at"]) {
|
|
1592
|
+
request.continueAt = config["continue-at"];
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
if (Object.prototype.hasOwnProperty.call(config, "crlf")) {
|
|
1596
|
+
request.crlf = config.crlf;
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
if (Object.prototype.hasOwnProperty.call(config, "clobber")) {
|
|
1600
|
+
request.clobber = config.clobber;
|
|
1601
|
+
}
|
|
1602
|
+
if (Object.prototype.hasOwnProperty.call(config, "remote-time")) {
|
|
1603
|
+
request.remoteTime = config["remote-time"];
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
// Global options
|
|
1607
|
+
if (Object.prototype.hasOwnProperty.call(global_, "verbose")) {
|
|
1608
|
+
request.verbose = global_.verbose;
|
|
1609
|
+
}
|
|
1610
|
+
if (Object.prototype.hasOwnProperty.call(global_, "silent")) {
|
|
1611
|
+
request.silent = global_.silent;
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
return request;
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
export function buildRequests(
|
|
1618
|
+
global_: GlobalConfig,
|
|
1619
|
+
stdin?: Word,
|
|
1620
|
+
stdinFile?: Word,
|
|
1621
|
+
): Request[] {
|
|
1622
|
+
if (!global_.configs.length) {
|
|
1623
|
+
// shouldn't happen
|
|
1624
|
+
warnf(global_, ["no-configs", "got empty config object"]);
|
|
1625
|
+
}
|
|
1626
|
+
return global_.configs.map((config) =>
|
|
1627
|
+
buildRequest(global_, config, stdin, stdinFile),
|
|
1628
|
+
);
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
export function getFirst(
|
|
1632
|
+
requests: Request[],
|
|
1633
|
+
warnings: Warnings,
|
|
1634
|
+
support?: Support,
|
|
1635
|
+
): Request {
|
|
1636
|
+
if (requests.length > 1) {
|
|
1637
|
+
warnings.push([
|
|
1638
|
+
"next",
|
|
1639
|
+
// TODO: better message, we might have two requests because of
|
|
1640
|
+
// --next or because of multiple curl commands or both
|
|
1641
|
+
"got " +
|
|
1642
|
+
requests.length +
|
|
1643
|
+
" curl requests, only converting the first one",
|
|
1644
|
+
]);
|
|
1645
|
+
}
|
|
1646
|
+
const request = requests[0];
|
|
1647
|
+
warnIfPartsIgnored(request, warnings, support);
|
|
1648
|
+
return request;
|
|
1649
|
+
}
|