]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - shared/extra-utils/requests/requests.ts
More robust optimize transcoding job
[github/Chocobozzz/PeerTube.git] / shared / extra-utils / requests / requests.ts
CommitLineData
c0e8b12e 1/* eslint-disable @typescript-eslint/no-floating-promises */
a1587156 2
9107d791 3import { decode } from 'querystring'
2d1ad5b9
C
4import * as request from 'supertest'
5import { URL } from 'url'
c0e8b12e
C
6import { HttpStatusCode } from '@shared/models'
7import { buildAbsoluteFixturePath } from '../miscs/tests'
09209296 8
c0e8b12e 9export type CommonRequestParams = {
a1587156
C
10 url: string
11 path?: string
a1587156 12 contentType?: string
4c280004 13 range?: string
9107d791 14 redirects?: number
012580d9 15 accept?: string
41d1d075 16 host?: string
c0e8b12e
C
17 token?: string
18 headers?: { [ name: string ]: string }
19 type?: string
20 xForwardedFor?: string
21 expectedStatus?: HttpStatusCode
22}
eec63bbc 23
c0e8b12e
C
24function makeRawRequest (url: string, expectedStatus?: HttpStatusCode, range?: string) {
25 const { host, protocol, pathname } = new URL(url)
eec63bbc 26
c0e8b12e 27 return makeGetRequest({ url: `${protocol}//${host}`, path: pathname, expectedStatus, range })
eec63bbc
C
28}
29
c0e8b12e
C
30function makeGetRequest (options: CommonRequestParams & {
31 query?: any
eec63bbc 32}) {
c0e8b12e
C
33 const req = request(options.url).get(options.path)
34 .query(options.query)
eec63bbc 35
c0e8b12e
C
36 return buildRequest(req, { contentType: 'application/json', expectedStatus: HttpStatusCode.BAD_REQUEST_400, ...options })
37}
eec63bbc 38
c0e8b12e
C
39function makeHTMLRequest (url: string, path: string) {
40 return makeGetRequest({
41 url,
42 path,
43 accept: 'text/html',
44 expectedStatus: HttpStatusCode.OK_200
45 })
46}
eec63bbc 47
c0e8b12e
C
48function makeActivityPubGetRequest (url: string, path: string, expectedStatus = HttpStatusCode.OK_200) {
49 return makeGetRequest({
50 url,
51 path,
52 expectedStatus: expectedStatus,
53 accept: 'application/activity+json,text/html;q=0.9,\\*/\\*;q=0.8'
54 })
0e1dc3e7
C
55}
56
c0e8b12e
C
57function makeDeleteRequest (options: CommonRequestParams) {
58 const req = request(options.url).delete(options.path)
59
60 return buildRequest(req, { accept: 'application/json', expectedStatus: HttpStatusCode.BAD_REQUEST_400, ...options })
61}
62
63function makeUploadRequest (options: CommonRequestParams & {
a1587156 64 method?: 'POST' | 'PUT'
d23dd9fb 65
a1587156 66 fields: { [ fieldName: string ]: any }
77e9f859 67 attaches?: { [ attachName: string ]: any | any[] }
0e1dc3e7 68}) {
c0e8b12e
C
69 let req = options.method === 'PUT'
70 ? request(options.url).put(options.path)
71 : request(options.url).post(options.path)
0e1dc3e7 72
c0e8b12e 73 req = buildRequest(req, { accept: 'application/json', expectedStatus: HttpStatusCode.BAD_REQUEST_400, ...options })
ac81d1a0 74
c0e8b12e 75 buildFields(req, options.fields)
0e1dc3e7 76
77e9f859 77 Object.keys(options.attaches || {}).forEach(attach => {
0e1dc3e7 78 const value = options.attaches[attach]
c0e8b12e 79
2769e297
C
80 if (Array.isArray(value)) {
81 req.attach(attach, buildAbsoluteFixturePath(value[0]), value[1])
82 } else {
83 req.attach(attach, buildAbsoluteFixturePath(value))
84 }
0e1dc3e7
C
85 })
86
d23dd9fb 87 return req
0e1dc3e7
C
88}
89
c0e8b12e 90function makePostBodyRequest (options: CommonRequestParams & {
a1587156 91 fields?: { [ fieldName: string ]: any }
0e1dc3e7 92}) {
c0e8b12e
C
93 const req = request(options.url).post(options.path)
94 .send(options.fields)
0e1dc3e7 95
c0e8b12e 96 return buildRequest(req, { accept: 'application/json', expectedStatus: HttpStatusCode.BAD_REQUEST_400, ...options })
0e1dc3e7
C
97}
98
99function makePutBodyRequest (options: {
a1587156
C
100 url: string
101 path: string
102 token?: string
103 fields: { [ fieldName: string ]: any }
c0e8b12e 104 expectedStatus?: HttpStatusCode
4bbfc6c6 105}) {
c0e8b12e
C
106 const req = request(options.url).put(options.path)
107 .send(options.fields)
4bbfc6c6 108
c0e8b12e 109 return buildRequest(req, { accept: 'application/json', expectedStatus: HttpStatusCode.BAD_REQUEST_400, ...options })
4bbfc6c6
C
110}
111
9107d791
C
112function decodeQueryString (path: string) {
113 return decode(path.split('?')[1])
114}
115
c1bc8ee4 116function unwrapBody <T> (test: request.Test): Promise<T> {
e8bd7ce7
C
117 return test.then(res => res.body)
118}
119
c1bc8ee4
C
120function unwrapText (test: request.Test): Promise<string> {
121 return test.then(res => res.text)
122}
123
0305db28
JB
124function unwrapBodyOrDecodeToJSON <T> (test: request.Test): Promise<T> {
125 return test.then(res => {
126 if (res.body instanceof Buffer) {
127 return JSON.parse(new TextDecoder().decode(res.body))
128 }
129
130 return res.body
131 })
132}
133
134function unwrapTextOrDecode (test: request.Test): Promise<string> {
135 return test.then(res => res.text || new TextDecoder().decode(res.body))
136}
137
0e1dc3e7
C
138// ---------------------------------------------------------------------------
139
140export {
e032aec9 141 makeHTMLRequest,
0e1dc3e7 142 makeGetRequest,
9107d791 143 decodeQueryString,
ac81d1a0 144 makeUploadRequest,
0e1dc3e7 145 makePostBodyRequest,
eec63bbc 146 makePutBodyRequest,
4bbfc6c6 147 makeDeleteRequest,
09209296 148 makeRawRequest,
2d1ad5b9 149 makeActivityPubGetRequest,
c1bc8ee4 150 unwrapBody,
0305db28
JB
151 unwrapTextOrDecode,
152 unwrapBodyOrDecodeToJSON,
c0e8b12e
C
153 unwrapText
154}
155
156// ---------------------------------------------------------------------------
157
158function buildRequest (req: request.Test, options: CommonRequestParams) {
159 if (options.contentType) req.set('Accept', options.contentType)
160 if (options.token) req.set('Authorization', 'Bearer ' + options.token)
161 if (options.range) req.set('Range', options.range)
162 if (options.accept) req.set('Accept', options.accept)
163 if (options.host) req.set('Host', options.host)
164 if (options.redirects) req.redirects(options.redirects)
165 if (options.expectedStatus) req.expect(options.expectedStatus)
166 if (options.xForwardedFor) req.set('X-Forwarded-For', options.xForwardedFor)
167 if (options.type) req.type(options.type)
168
169 Object.keys(options.headers || {}).forEach(name => {
170 req.set(name, options.headers[name])
171 })
172
173 return req
174}
175
176function buildFields (req: request.Test, fields: { [ fieldName: string ]: any }, namespace?: string) {
177 if (!fields) return
178
179 let formKey: string
180
181 for (const key of Object.keys(fields)) {
182 if (namespace) formKey = `${namespace}[${key}]`
183 else formKey = key
184
185 if (fields[key] === undefined) continue
186
187 if (Array.isArray(fields[key]) && fields[key].length === 0) {
188 req.field(key, null)
189 continue
190 }
191
192 if (fields[key] !== null && typeof fields[key] === 'object') {
193 buildFields(req, fields[key], formKey)
194 } else {
195 req.field(formKey, fields[key])
196 }
197 }
0e1dc3e7 198}