Skip to content

Commit

Permalink
fix: better handling multi-value headers
Browse files Browse the repository at this point in the history
  • Loading branch information
kukhariev committed May 28, 2022
1 parent c64cf5d commit 490e1e7
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 8 deletions.
2 changes: 1 addition & 1 deletion packages/core/src/handlers/cors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export class Cors {
this.allowedMethods.toString() || accessControlRequestMethod
);
const allowedHeaders =
this.allowedHeaders.toString() || getHeader(req, 'access-control-request-headers');
this.allowedHeaders.toString() || getHeader(req, 'access-control-request-headers', true);
allowedHeaders && res.setHeader('Access-Control-Allow-Headers', allowedHeaders);
res.setHeader('Access-Control-Max-Age', this.maxAge);
return;
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/handlers/tus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export class Tus<TFile extends UploadxFile> extends BaseHandler<TFile> {
* Create a file and send url to client
*/
async post(req: http.IncomingMessage, res: http.ServerResponse): Promise<TFile> {
const metadataHeader = getHeader(req, 'upload-metadata');
const metadataHeader = getHeader(req, 'upload-metadata', true);
const metadata = parseMetadata(metadataHeader);
const config: FileInit = { metadata };
config.userId = this.getUserId(req, res);
Expand All @@ -73,7 +73,7 @@ export class Tus<TFile extends UploadxFile> extends BaseHandler<TFile> {
*/
async patch(req: http.IncomingMessage, res: http.ServerResponse): Promise<TFile> {
const id = await this.getAndVerifyId(req, res);
const metadataHeader = getHeader(req, 'upload-metadata');
const metadataHeader = getHeader(req, 'upload-metadata', true);
const metadata = metadataHeader && parseMetadata(metadataHeader);
metadata && (await this.storage.update({ id }, { metadata, id }));
const start = Number(getHeader(req, 'upload-offset'));
Expand Down
14 changes: 12 additions & 2 deletions packages/core/src/utils/http.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as http from 'http';
import { getLastEntry } from './primitives';

export interface IncomingMessageWithBody<T = any> extends http.IncomingMessage {
body?: T;
Expand Down Expand Up @@ -57,9 +58,18 @@ export async function getMetadata(
return { ...JSON.parse(raw) } as Record<any, any>;
}

export function getHeader(req: http.IncomingMessage, name: string): string {
/**
Retrieve the value of a specific header of an HTTP request.
@param req - The request object.
@param name - The name of the header.
@param all - If true, returns all values of the header, comma-separated, otherwise returns the last value.
*/
export function getHeader(req: http.IncomingMessage, name: string, all = false): string {
const raw = req.headers?.[name.toLowerCase()];
return Array.isArray(raw) ? raw[0] : raw || '';
if (!raw) return '';
return all
? raw.toString().trim()
: getLastEntry(Array.isArray(raw) ? raw : raw.split(',')).trim();
}

export function appendHeader(
Expand Down
6 changes: 5 additions & 1 deletion packages/core/src/utils/primitives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,14 @@ export function toMilliseconds(value: string | number | undefined): number | nul
return duration(value);
}

export function first<T>(val: T | T[]): T {
export function getFirstEntry<T>(val: T | T[]): T {
return Array.isArray(val) ? val[0] : val;
}

export function getLastEntry<T>(val: T | T[]): T {
return Array.isArray(val) ? val[val.length - 1] : val;
}

export const memoize = <T, K>(fn: (val: T) => K): ((val: T) => K) => {
const cache = new Cache<K>(1000, 0);
const cached = (val: T): K => {
Expand Down
14 changes: 12 additions & 2 deletions test/util.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,19 @@ describe('utils', () => {
expect(utils.getHeader(req, 'head')).toBe('value');
});

it('getHeader(array)', () => {
req.headers = { head: ['value1', 'value2 '] };
expect(utils.getHeader(req, 'head')).toBe('value2');
});

it('getHeader(multiple)', () => {
req.headers = { head: ['value1', 'value2'] };
expect(utils.getHeader(req, 'head')).toBe('value1');
req.headers = { head: 'value1 ,value2' };
expect(utils.getHeader(req, 'head')).toBe('value2');
});

it('getHeader(multiple, all)', () => {
req.headers = { head: 'value1,value2 ' };
expect(utils.getHeader(req, 'head', true)).toBe('value1,value2');
});

it('getBaseUrl(no-host)', () => {
Expand Down

0 comments on commit 490e1e7

Please sign in to comment.