UNPKG

@nodescript/stdlib

Version:
117 lines (116 loc) 3.79 kB
import { determineRequestBody, FetchResponseType, headersToObject, HttpRequestFailed, mergeUrlQuery, readResponse, } from '../lib/web.js'; export const module = { version: '1.6.4', moduleName: 'Web / Fetch', description: ` Sends an HTTP request using natively available Fetch API. Note: when sent from the browser, the request is subject to Cross-Origin Resource Sharing (CORS) policy, along with other limitations. Use HTTP Request node for a general purpose HTTP client. `, keywords: ['http', 'request'], params: { method: { schema: { type: 'string', enum: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'], default: 'GET', }, }, url: { schema: { type: 'string' }, }, query: { schema: { type: 'object', properties: {}, additionalProperties: { type: 'string', optional: true }, }, advanced: true, }, headers: { schema: { type: 'object', properties: {}, additionalProperties: { type: 'string', optional: true }, }, advanced: true, }, body: { schema: { type: 'any' }, hideValue: true, advanced: true, }, throw: { schema: { type: 'boolean', default: true }, advanced: true, }, responseType: { schema: { type: 'string', enum: Object.values(FetchResponseType), default: FetchResponseType.AUTO, }, advanced: true, }, }, result: { async: true, schema: { type: 'object', properties: { status: { type: 'number' }, url: { type: 'string' }, headers: { type: 'object', additionalProperties: { type: 'any' }, }, body: { type: 'any' }, } }, }, cacheMode: 'always', evalMode: 'manual', }; export const compute = async (params, ctx) => { const { method, url, query, headers, body, responseType = FetchResponseType.AUTO, } = params; if (!url) { // Do not send requests to self by default return undefined; } if (!/^https?:\/\//.test(url)) { throw new Error('URL must start with http:// or https://'); } const actualUrl = mergeUrlQuery(url, query); const actualHeaders = prepareHeaders(headers); const [actualBody, bodyContentType] = determineRequestBody(method, body); if (bodyContentType && !actualHeaders.has('Content-Type')) { actualHeaders.set('Content-Type', bodyContentType); } const res = await fetch(actualUrl, { method, headers: actualHeaders, body: actualBody, }); if (params.throw && !res.ok) { const responseBody = await res.text(); const details = ctx.lib.parseJson(responseBody) ?? { response: responseBody }; throw new HttpRequestFailed(res.status, method, url, details); } const resContentType = res.headers.get('content-type') ?? 'text/plain'; return { url: res.url, status: res.status, headers: headersToObject(res.headers), body: await readResponse(res, responseType, resContentType), }; }; function prepareHeaders(headers) { const entries = {}; for (const [key, value] of Object.entries(headers)) { if (value === undefined) { continue; } entries[key] = String(value); } return new Headers(entries); }