123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- /* eslint-disable @typescript-eslint/no-floating-promises */
- import { decode } from 'querystring'
- import request from 'supertest'
- import { URL } from 'url'
- import { buildAbsoluteFixturePath } from '@shared/core-utils'
- import { HttpStatusCode } from '@shared/models'
- export type CommonRequestParams = {
- url: string
- path?: string
- contentType?: string
- range?: string
- redirects?: number
- accept?: string
- host?: string
- token?: string
- headers?: { [ name: string ]: string }
- type?: string
- xForwardedFor?: string
- expectedStatus?: HttpStatusCode
- }
- function makeRawRequest (url: string, expectedStatus?: HttpStatusCode, range?: string) {
- const { host, protocol, pathname } = new URL(url)
- return makeGetRequest({ url: `${protocol}//${host}`, path: pathname, expectedStatus, range })
- }
- function makeGetRequest (options: CommonRequestParams & {
- query?: any
- rawQuery?: string
- }) {
- const req = request(options.url).get(options.path)
- if (options.query) req.query(options.query)
- if (options.rawQuery) req.query(options.rawQuery)
- return buildRequest(req, { contentType: 'application/json', expectedStatus: HttpStatusCode.BAD_REQUEST_400, ...options })
- }
- function makeHTMLRequest (url: string, path: string) {
- return makeGetRequest({
- url,
- path,
- accept: 'text/html',
- expectedStatus: HttpStatusCode.OK_200
- })
- }
- function makeActivityPubGetRequest (url: string, path: string, expectedStatus = HttpStatusCode.OK_200) {
- return makeGetRequest({
- url,
- path,
- expectedStatus,
- accept: 'application/activity+json,text/html;q=0.9,\\*/\\*;q=0.8'
- })
- }
- function makeDeleteRequest (options: CommonRequestParams & {
- query?: any
- rawQuery?: string
- }) {
- const req = request(options.url).delete(options.path)
- if (options.query) req.query(options.query)
- if (options.rawQuery) req.query(options.rawQuery)
- return buildRequest(req, { accept: 'application/json', expectedStatus: HttpStatusCode.BAD_REQUEST_400, ...options })
- }
- function makeUploadRequest (options: CommonRequestParams & {
- method?: 'POST' | 'PUT'
- fields: { [ fieldName: string ]: any }
- attaches?: { [ attachName: string ]: any | any[] }
- }) {
- let req = options.method === 'PUT'
- ? request(options.url).put(options.path)
- : request(options.url).post(options.path)
- req = buildRequest(req, { accept: 'application/json', expectedStatus: HttpStatusCode.BAD_REQUEST_400, ...options })
- buildFields(req, options.fields)
- Object.keys(options.attaches || {}).forEach(attach => {
- const value = options.attaches[attach]
- if (!value) return
- if (Array.isArray(value)) {
- req.attach(attach, buildAbsoluteFixturePath(value[0]), value[1])
- } else {
- req.attach(attach, buildAbsoluteFixturePath(value))
- }
- })
- return req
- }
- function makePostBodyRequest (options: CommonRequestParams & {
- fields?: { [ fieldName: string ]: any }
- }) {
- const req = request(options.url).post(options.path)
- .send(options.fields)
- return buildRequest(req, { accept: 'application/json', expectedStatus: HttpStatusCode.BAD_REQUEST_400, ...options })
- }
- function makePutBodyRequest (options: {
- url: string
- path: string
- token?: string
- fields: { [ fieldName: string ]: any }
- expectedStatus?: HttpStatusCode
- }) {
- const req = request(options.url).put(options.path)
- .send(options.fields)
- return buildRequest(req, { accept: 'application/json', expectedStatus: HttpStatusCode.BAD_REQUEST_400, ...options })
- }
- function decodeQueryString (path: string) {
- return decode(path.split('?')[1])
- }
- function unwrapBody <T> (test: request.Test): Promise<T> {
- return test.then(res => res.body)
- }
- function unwrapText (test: request.Test): Promise<string> {
- return test.then(res => res.text)
- }
- function unwrapBodyOrDecodeToJSON <T> (test: request.Test): Promise<T> {
- return test.then(res => {
- if (res.body instanceof Buffer) {
- return JSON.parse(new TextDecoder().decode(res.body))
- }
- return res.body
- })
- }
- function unwrapTextOrDecode (test: request.Test): Promise<string> {
- return test.then(res => res.text || new TextDecoder().decode(res.body))
- }
- // ---------------------------------------------------------------------------
- export {
- makeHTMLRequest,
- makeGetRequest,
- decodeQueryString,
- makeUploadRequest,
- makePostBodyRequest,
- makePutBodyRequest,
- makeDeleteRequest,
- makeRawRequest,
- makeActivityPubGetRequest,
- unwrapBody,
- unwrapTextOrDecode,
- unwrapBodyOrDecodeToJSON,
- unwrapText
- }
- // ---------------------------------------------------------------------------
- function buildRequest (req: request.Test, options: CommonRequestParams) {
- if (options.contentType) req.set('Accept', options.contentType)
- if (options.token) req.set('Authorization', 'Bearer ' + options.token)
- if (options.range) req.set('Range', options.range)
- if (options.accept) req.set('Accept', options.accept)
- if (options.host) req.set('Host', options.host)
- if (options.redirects) req.redirects(options.redirects)
- if (options.xForwardedFor) req.set('X-Forwarded-For', options.xForwardedFor)
- if (options.type) req.type(options.type)
- Object.keys(options.headers || {}).forEach(name => {
- req.set(name, options.headers[name])
- })
- return req.expect((res) => {
- if (options.expectedStatus && res.status !== options.expectedStatus) {
- throw new Error(`Expected status ${options.expectedStatus}, got ${res.status}. ` +
- `\nThe server responded this error: "${res.body?.error ?? res.text}".\n` +
- 'You may take a closer look at the logs. To see how to do so, check out this page: ' +
- 'https://github.com/Chocobozzz/PeerTube/blob/develop/support/doc/development/tests.md#debug-server-logs')
- }
- return res
- })
- }
- function buildFields (req: request.Test, fields: { [ fieldName: string ]: any }, namespace?: string) {
- if (!fields) return
- let formKey: string
- for (const key of Object.keys(fields)) {
- if (namespace) formKey = `${namespace}[${key}]`
- else formKey = key
- if (fields[key] === undefined) continue
- if (Array.isArray(fields[key]) && fields[key].length === 0) {
- req.field(key, [])
- continue
- }
- if (fields[key] !== null && typeof fields[key] === 'object') {
- buildFields(req, fields[key], formKey)
- } else {
- req.field(formKey, fields[key])
- }
- }
- }
|