@mojojs/core
Version:
Real-time web framework
169 lines • 4.85 kB
JavaScript
import { headerParams } from '@mojojs/util';
const HOP_BY_HOP = [
'connection',
'keep-alive',
'proxy-authenticate',
'proxy-authorization',
'te',
'trailer',
'transfer-encoding',
'upgrade'
];
/**
* HTTP header class.
*/
export class Headers {
constructor(init = []) {
this._init = init;
}
/**
* Append header value.
*/
append(name, value) {
const lowerCase = name.toLowerCase();
const headers = this._getHeaders();
if (headers[lowerCase] === undefined)
return this.set(name, value);
if (lowerCase === 'set-cookie') {
headers[lowerCase].values.push(value);
}
else {
headers[lowerCase].values = [[...headers[lowerCase].values, value].join(', ')];
}
return this;
}
/**
* Clone headers.
*/
clone() {
return new Headers(this.toArray());
}
/**
* Remove hop-by-hop headers that should not be retransmitted.
*/
dehop() {
const headers = this._getHeaders();
HOP_BY_HOP.forEach(name => delete headers[name]);
return this;
}
/**
* Get header value.
*/
get(name) {
const header = this._getHeaders()[name.toLowerCase()];
if (header === undefined)
return null;
return header.values.join(', ');
}
/**
* Get all headers values individually.
*/
getAll(name) {
const values = this._getHeaders()[name.toLowerCase()]?.values ?? [];
return [...values];
}
/**
* Get web links from `Link` header according to RFC5988.
* @link http://tools.ietf.org/html/rfc5988
* @example
* // Extract information about next page
* const {link, title} = headers.getLinks().next;
*/
getLinks() {
var _a;
const data = {};
let value = this.get('Link') ?? '';
while (value.length > 0) {
const linkMatch = value.match(/^[,\s]*<(.+?)>(.+)$/);
if (linkMatch === null)
break;
const link = linkMatch[1];
const { params, remainder } = headerParams(linkMatch[2]);
value = remainder;
if (params.rel !== undefined)
data[_a = params.rel] ?? (data[_a] = { ...params, link });
}
return data;
}
/**
* Remove header.
*/
remove(name) {
delete this._getHeaders()[name.toLowerCase()];
return this;
}
/**
* Set header value.
*/
set(name, value) {
const lowerCase = name.toLowerCase();
this._getHeaders()[lowerCase] = { normalCase: name, values: [value] };
return this;
}
/**
* Set web links to `Link` header according to RFC5988.
* @link http://tools.ietf.org/html/rfc5988
* @example
* // Link to next and previous page
* headers.setLinks({next: 'http://example.com/foo', prev: 'http://example.com/bar'});
*/
setLinks(links) {
const value = Object.entries(links)
.map(([rel, link]) => `<${link}>; rel="${rel}"`)
.join(', ');
return this.set('Link', value);
}
/**
* Convert headers into a plain array of name/value pairs.
*/
toArray() {
const array = [];
for (const header of Object.values(this._getHeaders())) {
for (const value of header.values) {
array.push(header.normalCase, value);
}
}
return array;
}
/**
* Convert headers into a plain object.
*/
toObject() {
const object = {};
for (const header of Object.values(this._getHeaders())) {
object[header.normalCase] = header.values.join(', ');
}
return object;
}
/**
* Convert headers to string.
*/
toString() {
const lines = [];
for (const header of Object.values(this._getHeaders())) {
for (const value of header.values) {
lines.push(`${header.normalCase}: ${value}\r\n`);
}
}
return lines.join('') + '\r\n';
}
_getHeaders() {
if (this._headers === undefined) {
const headers = (this._headers = {});
const init = this._init;
for (let i = 0; i < init.length; i += 2) {
const name = init[i];
const value = init[i + 1];
const lowerCase = name.toLowerCase();
if (headers[lowerCase] === undefined) {
headers[lowerCase] = { normalCase: name, values: [value] };
}
else {
headers[lowerCase].values.push(value);
}
}
}
return this._headers;
}
}
//# sourceMappingURL=headers.js.map