1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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: {},
};
};