Skip to content

Commit 29b4e68

Browse files
authored
feat: Add getters for headers (#111)
* Add methods to get headers from request * Write tests for getHeader and getAllHeaders * Update other RequestModel methods to use getHeader
1 parent 0841385 commit 29b4e68

2 files changed

Lines changed: 73 additions & 33 deletions

File tree

src/Service/Request.service.js

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,47 @@ export default class RequestService extends DependencyAwareClass {
4141
return typeof queryParameters[parameter] !== 'undefined' ? queryParameters[parameter] : ifNull;
4242
}
4343

44+
/**
45+
* Get all HTTP headers included in the request.
46+
*
47+
* @returns {object} An object with a key for each header.
48+
*/
49+
getAllHeaders() {
50+
return { ...this.getContainer().getEvent().headers };
51+
}
52+
53+
/**
54+
* Get an HTTP header from the request.
55+
*
56+
* The header name is case-insensitive.
57+
*
58+
* @param {string} name The name of the header.
59+
* @param {string} [whenMissing] Value to return if the header is missing.
60+
* (default: empty string)
61+
*
62+
* @returns {string}
63+
*/
64+
getHeader(name: string, whenMissing: string = '') {
65+
const headers = this.getAllHeaders();
66+
if (!headers) {
67+
return whenMissing;
68+
}
69+
const lowerName = name.toLowerCase();
70+
const key = Object.keys(headers).find((k) => k.toLowerCase() === lowerName);
71+
return (key && headers[key]) || whenMissing;
72+
}
73+
4474
/**
4575
* Get authorization token
4676
* @return {*}
4777
*/
4878
getAuthorizationToken() {
49-
const { headers } = this.getContainer().getEvent();
50-
51-
if (typeof headers.Authorization === 'undefined' && typeof headers.authorization === 'undefined') {
79+
const authorization = this.getHeader('Authorization');
80+
if (!authorization) {
5281
return null;
5382
}
5483

55-
const tokenParts = headers[typeof headers.Authorization === 'undefined' ? 'authorization' : 'Authorization'].split(' ');
84+
const tokenParts = authorization.split(' ');
5685
const tokenValue = tokenParts[1];
5786

5887
if (!(tokenParts[0].toLowerCase() === 'bearer' && tokenValue)) {
@@ -103,30 +132,22 @@ export default class RequestService extends DependencyAwareClass {
103132
}
104133

105134
if (event.httpMethod === 'POST' || requestType === REQUEST_TYPES.POST) {
135+
const contentType = this.getHeader('Content-Type');
106136
let queryParameters = {};
107137

108-
if (
109-
(typeof event.headers['Content-Type'] !== 'undefined' && event.headers['Content-Type'].includes('application/x-www-form-urlencoded')) ||
110-
(typeof event.headers['content-type'] !== 'undefined' && event.headers['content-type'].includes('application/x-www-form-urlencoded'))
111-
) {
138+
if (contentType.includes('application/x-www-form-urlencoded')) {
112139
queryParameters = QueryString.parse(event.body);
113140
}
114141

115-
if (
116-
(typeof event.headers['Content-Type'] !== 'undefined' && event.headers['Content-Type'].includes('application/json')) ||
117-
(typeof event.headers['content-type'] !== 'undefined' && event.headers['content-type'].includes('application/json'))
118-
) {
142+
if (contentType.includes('application/json')) {
119143
try {
120144
queryParameters = JSON.parse(event.body);
121145
} catch {
122146
queryParameters = {};
123147
}
124148
}
125149

126-
if (
127-
(typeof event.headers['Content-Type'] !== 'undefined' && event.headers['Content-Type'].includes('text/xml')) ||
128-
(typeof event.headers['content-type'] !== 'undefined' && event.headers['content-type'].includes('text/xml'))
129-
) {
150+
if (contentType.includes('text/xml')) {
130151
XML2JS.parseString(event.body, (error, result) => {
131152
if (error) {
132153
queryParameters = {};
@@ -135,12 +156,11 @@ export default class RequestService extends DependencyAwareClass {
135156
}
136157
});
137158
}
138-
if (
139-
(typeof event.headers['Content-Type'] !== 'undefined' && event.headers['Content-Type'].includes('multipart/form-data')) ||
140-
(typeof event.headers['content-type'] !== 'undefined' && event.headers['content-type'].includes('multipart/form-data'))
141-
) {
159+
160+
if (contentType.includes('multipart/form-data')) {
142161
queryParameters = this.parseForm(true);
143162
}
163+
144164
return typeof queryParameters !== 'undefined' ? queryParameters : {};
145165
}
146166

@@ -170,19 +190,7 @@ export default class RequestService extends DependencyAwareClass {
170190
* @return {*}
171191
*/
172192
getUserBrowserAndDevice() {
173-
const { headers } = this.getContainer().getEvent();
174-
let userAgent = null;
175-
176-
if (typeof headers !== 'object' || headers === null) {
177-
return null;
178-
}
179-
180-
Object.keys(headers).forEach((header) => {
181-
if (header.toUpperCase() === 'USER-AGENT') {
182-
userAgent = headers[header];
183-
}
184-
});
185-
193+
const userAgent = this.getHeader('user-agent', null);
186194
if (userAgent === null) {
187195
return null;
188196
}

tests/unit/Service/Request.service.test.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,4 +210,36 @@ describe('Service/RequestService', () => {
210210
});
211211
});
212212
});
213+
214+
describe('getAllHeaders()', () => {
215+
const event = { ...getEvent };
216+
const di = new DependencyInjection(CONFIGURATION, event, getContext);
217+
const request = new RequestService(di);
218+
219+
it('should return all headers from the event', () => {
220+
expect(request.getAllHeaders()).toStrictEqual(getEvent.headers);
221+
});
222+
});
223+
224+
describe('getHeader()', () => {
225+
const event = { ...getEvent };
226+
const di = new DependencyInjection(CONFIGURATION, event, getContext);
227+
const request = new RequestService(di);
228+
229+
it('should return the specified header', () => {
230+
expect(request.getHeader('Accept')).toEqual(event.headers.Accept);
231+
});
232+
233+
it("should return '' by default if header is missing", () => {
234+
expect(request.getHeader('Authorization')).toEqual('');
235+
});
236+
237+
it("should return `whenMissing` if header is missing", () => {
238+
expect(request.getHeader('Authorization', 'none')).toEqual('none');
239+
});
240+
241+
it('should not be case-sensitive', () => {
242+
expect(request.getHeader('accept')).toEqual(event.headers.Accept);
243+
});
244+
});
213245
});

0 commit comments

Comments
 (0)