diff options
Diffstat (limited to 'shared/server-commands/requests/requests.ts')
-rw-r--r-- | shared/server-commands/requests/requests.ts | 259 |
1 files changed, 0 insertions, 259 deletions
diff --git a/shared/server-commands/requests/requests.ts b/shared/server-commands/requests/requests.ts deleted file mode 100644 index 8227017eb..000000000 --- a/shared/server-commands/requests/requests.ts +++ /dev/null | |||
@@ -1,259 +0,0 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-floating-promises */ | ||
2 | |||
3 | import { decode } from 'querystring' | ||
4 | import request from 'supertest' | ||
5 | import { URL } from 'url' | ||
6 | import { buildAbsoluteFixturePath, pick } from '@shared/core-utils' | ||
7 | import { HttpStatusCode } from '@shared/models' | ||
8 | |||
9 | export type CommonRequestParams = { | ||
10 | url: string | ||
11 | path?: string | ||
12 | contentType?: string | ||
13 | responseType?: string | ||
14 | range?: string | ||
15 | redirects?: number | ||
16 | accept?: string | ||
17 | host?: string | ||
18 | token?: string | ||
19 | headers?: { [ name: string ]: string } | ||
20 | type?: string | ||
21 | xForwardedFor?: string | ||
22 | expectedStatus?: HttpStatusCode | ||
23 | } | ||
24 | |||
25 | function makeRawRequest (options: { | ||
26 | url: string | ||
27 | token?: string | ||
28 | expectedStatus?: HttpStatusCode | ||
29 | range?: string | ||
30 | query?: { [ id: string ]: string } | ||
31 | method?: 'GET' | 'POST' | ||
32 | headers?: { [ name: string ]: string } | ||
33 | }) { | ||
34 | const { host, protocol, pathname } = new URL(options.url) | ||
35 | |||
36 | const reqOptions = { | ||
37 | url: `${protocol}//${host}`, | ||
38 | path: pathname, | ||
39 | contentType: undefined, | ||
40 | |||
41 | ...pick(options, [ 'expectedStatus', 'range', 'token', 'query', 'headers' ]) | ||
42 | } | ||
43 | |||
44 | if (options.method === 'POST') { | ||
45 | return makePostBodyRequest(reqOptions) | ||
46 | } | ||
47 | |||
48 | return makeGetRequest(reqOptions) | ||
49 | } | ||
50 | |||
51 | function makeGetRequest (options: CommonRequestParams & { | ||
52 | query?: any | ||
53 | rawQuery?: string | ||
54 | }) { | ||
55 | const req = request(options.url).get(options.path) | ||
56 | |||
57 | if (options.query) req.query(options.query) | ||
58 | if (options.rawQuery) req.query(options.rawQuery) | ||
59 | |||
60 | return buildRequest(req, { contentType: 'application/json', expectedStatus: HttpStatusCode.BAD_REQUEST_400, ...options }) | ||
61 | } | ||
62 | |||
63 | function makeHTMLRequest (url: string, path: string) { | ||
64 | return makeGetRequest({ | ||
65 | url, | ||
66 | path, | ||
67 | accept: 'text/html', | ||
68 | expectedStatus: HttpStatusCode.OK_200 | ||
69 | }) | ||
70 | } | ||
71 | |||
72 | function makeActivityPubGetRequest (url: string, path: string, expectedStatus = HttpStatusCode.OK_200) { | ||
73 | return makeGetRequest({ | ||
74 | url, | ||
75 | path, | ||
76 | expectedStatus, | ||
77 | accept: 'application/activity+json,text/html;q=0.9,\\*/\\*;q=0.8' | ||
78 | }) | ||
79 | } | ||
80 | |||
81 | function makeDeleteRequest (options: CommonRequestParams & { | ||
82 | query?: any | ||
83 | rawQuery?: string | ||
84 | }) { | ||
85 | const req = request(options.url).delete(options.path) | ||
86 | |||
87 | if (options.query) req.query(options.query) | ||
88 | if (options.rawQuery) req.query(options.rawQuery) | ||
89 | |||
90 | return buildRequest(req, { accept: 'application/json', expectedStatus: HttpStatusCode.BAD_REQUEST_400, ...options }) | ||
91 | } | ||
92 | |||
93 | function makeUploadRequest (options: CommonRequestParams & { | ||
94 | method?: 'POST' | 'PUT' | ||
95 | |||
96 | fields: { [ fieldName: string ]: any } | ||
97 | attaches?: { [ attachName: string ]: any | any[] } | ||
98 | }) { | ||
99 | let req = options.method === 'PUT' | ||
100 | ? request(options.url).put(options.path) | ||
101 | : request(options.url).post(options.path) | ||
102 | |||
103 | req = buildRequest(req, { accept: 'application/json', expectedStatus: HttpStatusCode.BAD_REQUEST_400, ...options }) | ||
104 | |||
105 | buildFields(req, options.fields) | ||
106 | |||
107 | Object.keys(options.attaches || {}).forEach(attach => { | ||
108 | const value = options.attaches[attach] | ||
109 | if (!value) return | ||
110 | |||
111 | if (Array.isArray(value)) { | ||
112 | req.attach(attach, buildAbsoluteFixturePath(value[0]), value[1]) | ||
113 | } else { | ||
114 | req.attach(attach, buildAbsoluteFixturePath(value)) | ||
115 | } | ||
116 | }) | ||
117 | |||
118 | return req | ||
119 | } | ||
120 | |||
121 | function makePostBodyRequest (options: CommonRequestParams & { | ||
122 | fields?: { [ fieldName: string ]: any } | ||
123 | }) { | ||
124 | const req = request(options.url).post(options.path) | ||
125 | .send(options.fields) | ||
126 | |||
127 | return buildRequest(req, { accept: 'application/json', expectedStatus: HttpStatusCode.BAD_REQUEST_400, ...options }) | ||
128 | } | ||
129 | |||
130 | function makePutBodyRequest (options: { | ||
131 | url: string | ||
132 | path: string | ||
133 | token?: string | ||
134 | fields: { [ fieldName: string ]: any } | ||
135 | expectedStatus?: HttpStatusCode | ||
136 | headers?: { [name: string]: string } | ||
137 | }) { | ||
138 | const req = request(options.url).put(options.path) | ||
139 | .send(options.fields) | ||
140 | |||
141 | return buildRequest(req, { accept: 'application/json', expectedStatus: HttpStatusCode.BAD_REQUEST_400, ...options }) | ||
142 | } | ||
143 | |||
144 | function decodeQueryString (path: string) { | ||
145 | return decode(path.split('?')[1]) | ||
146 | } | ||
147 | |||
148 | // --------------------------------------------------------------------------- | ||
149 | |||
150 | function unwrapBody <T> (test: request.Test): Promise<T> { | ||
151 | return test.then(res => res.body) | ||
152 | } | ||
153 | |||
154 | function unwrapText (test: request.Test): Promise<string> { | ||
155 | return test.then(res => res.text) | ||
156 | } | ||
157 | |||
158 | function unwrapBodyOrDecodeToJSON <T> (test: request.Test): Promise<T> { | ||
159 | return test.then(res => { | ||
160 | if (res.body instanceof Buffer) { | ||
161 | try { | ||
162 | return JSON.parse(new TextDecoder().decode(res.body)) | ||
163 | } catch (err) { | ||
164 | console.error('Cannot decode JSON.', { res, body: res.body instanceof Buffer ? res.body.toString() : res.body }) | ||
165 | throw err | ||
166 | } | ||
167 | } | ||
168 | |||
169 | if (res.text) { | ||
170 | try { | ||
171 | return JSON.parse(res.text) | ||
172 | } catch (err) { | ||
173 | console.error('Cannot decode json', { res, text: res.text }) | ||
174 | throw err | ||
175 | } | ||
176 | } | ||
177 | |||
178 | return res.body | ||
179 | }) | ||
180 | } | ||
181 | |||
182 | function unwrapTextOrDecode (test: request.Test): Promise<string> { | ||
183 | return test.then(res => res.text || new TextDecoder().decode(res.body)) | ||
184 | } | ||
185 | |||
186 | // --------------------------------------------------------------------------- | ||
187 | |||
188 | export { | ||
189 | makeHTMLRequest, | ||
190 | makeGetRequest, | ||
191 | decodeQueryString, | ||
192 | makeUploadRequest, | ||
193 | makePostBodyRequest, | ||
194 | makePutBodyRequest, | ||
195 | makeDeleteRequest, | ||
196 | makeRawRequest, | ||
197 | makeActivityPubGetRequest, | ||
198 | unwrapBody, | ||
199 | unwrapTextOrDecode, | ||
200 | unwrapBodyOrDecodeToJSON, | ||
201 | unwrapText | ||
202 | } | ||
203 | |||
204 | // --------------------------------------------------------------------------- | ||
205 | |||
206 | function buildRequest (req: request.Test, options: CommonRequestParams) { | ||
207 | if (options.contentType) req.set('Accept', options.contentType) | ||
208 | if (options.responseType) req.responseType(options.responseType) | ||
209 | if (options.token) req.set('Authorization', 'Bearer ' + options.token) | ||
210 | if (options.range) req.set('Range', options.range) | ||
211 | if (options.accept) req.set('Accept', options.accept) | ||
212 | if (options.host) req.set('Host', options.host) | ||
213 | if (options.redirects) req.redirects(options.redirects) | ||
214 | if (options.xForwardedFor) req.set('X-Forwarded-For', options.xForwardedFor) | ||
215 | if (options.type) req.type(options.type) | ||
216 | |||
217 | Object.keys(options.headers || {}).forEach(name => { | ||
218 | req.set(name, options.headers[name]) | ||
219 | }) | ||
220 | |||
221 | return req.expect(res => { | ||
222 | if (options.expectedStatus && res.status !== options.expectedStatus) { | ||
223 | const err = new Error(`Expected status ${options.expectedStatus}, got ${res.status}. ` + | ||
224 | `\nThe server responded: "${res.body?.error ?? res.text}".\n` + | ||
225 | 'You may take a closer look at the logs. To see how to do so, check out this page: ' + | ||
226 | 'https://github.com/Chocobozzz/PeerTube/blob/develop/support/doc/development/tests.md#debug-server-logs'); | ||
227 | |||
228 | (err as any).res = res | ||
229 | |||
230 | throw err | ||
231 | } | ||
232 | |||
233 | return res | ||
234 | }) | ||
235 | } | ||
236 | |||
237 | function buildFields (req: request.Test, fields: { [ fieldName: string ]: any }, namespace?: string) { | ||
238 | if (!fields) return | ||
239 | |||
240 | let formKey: string | ||
241 | |||
242 | for (const key of Object.keys(fields)) { | ||
243 | if (namespace) formKey = `${namespace}[${key}]` | ||
244 | else formKey = key | ||
245 | |||
246 | if (fields[key] === undefined) continue | ||
247 | |||
248 | if (Array.isArray(fields[key]) && fields[key].length === 0) { | ||
249 | req.field(key, []) | ||
250 | continue | ||
251 | } | ||
252 | |||
253 | if (fields[key] !== null && typeof fields[key] === 'object') { | ||
254 | buildFields(req, fields[key], formKey) | ||
255 | } else { | ||
256 | req.field(formKey, fields[key]) | ||
257 | } | ||
258 | } | ||
259 | } | ||