import { parse as parseContentType } from 'content-type'; import { HafasError } from 'db-vendo-client/lib/errors.js'; export const checkIfVendoResponseIsOk = (_) => { const { body, errProps: baseErrProps } = _, errProps = { ...baseErrProps }; if (body.id) errProps.hafasResponseId = body.id; // Because we want more accurate stack traces, we don't construct the error here, // but only return the constructor & error message. const getError = (_) => { // mutating here is ugly but pragmatic if (_.fehlerNachricht.ueberschrift) errProps.hafasMessage = _.fehlerNachricht.ueberschrift; if (_.fehlerNachricht.text) errProps.hafasDescription = _.fehlerNachricht.text; return { Error: HafasError, message: errProps.hafasMessage || 'unknown error', props: { code: _.fehlerNachricht.code }, }; }; if (body.fehlerNachricht || body.errors) { // TODO better handling const {Error: HafasError, message, props} = getError(body); throw new HafasError(message, body.err || body.errors, {...errProps, ...props}); } }, vendoRequest = async (ctx, userAgent, reqData) => { const {profile, opt} = ctx, endpoint = reqData.endpoint; delete reqData.endpoint; const rawReqBody = profile.transformReqBody(ctx, reqData.body), reqOptions = profile.transformReq(ctx, { agent: null, keepalive: true, method: reqData.method, redirect: 'follow', body: JSON.stringify(rawReqBody), query: reqData.query, headers: { 'Content-Type': 'application/json', // 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Accept': 'application/json', 'Accept-Language': opt.language || profile.defaultLanguage || 'en', 'user-agent': userAgent, ...reqData.headers, }, }), url = `${[ endpoint, reqData?.path ].filter(x => typeof x === 'string' && x.length > 0).join('/')}?${(new URLSearchParams(reqOptions.query)).toString()}`, fetchReq = new Request(url, reqOptions), res = await fetch(url, reqOptions), errProps = { // todo [breaking]: assign as non-enumerable property request: fetchReq, // todo [breaking]: assign as non-enumerable property response: res, url, }; if (!res.ok) { // todo [breaking]: make this a FetchError or a HafasClientError? console.log(JSON.stringify(res), await res.text()); const err = new Error(res.statusText); Object.assign(err, errProps); throw err; } const cType = res.headers.get('content-type'); if (cType) { const { type } = parseContentType(cType); // For some reason, the reqOptions.headers object is sometimes a plain object // and sometimes a Headers object (In browser env). For the latter, .get() must // be used. if (type !== reqOptions.headers['Accept'] && type !== reqOptions.headers.get('Accept')) throw new HafasError('invalid/unsupported response content-type: ' + cType, null, errProps); } const body = JSON.parse(await res.text()); checkIfVendoResponseIsOk({ body, errProps }); return { res: body, common: {}, }; };