@webscale-networks/cloudedge-handlers
Version:
Webscale Networks CloudEDGE Handlers for cloud-agnostic edge function execution
189 lines (177 loc) • 5.63 kB
JavaScript
'use strict';
// A generic header class for retrieving, iterating, adding and removing
// headers.
//
// Use cases:
//
// Iterating over all headers:
// for (const [header_name, values] of headers) {
// for (const value in values) {
// ...
// }
// }
//
// Retrieving a header:
// headers.get('header_name') // returns header values or undefined.
//
// Adding the header 'Webscale': 'is cool' while preserving any existing
// 'Webscale' headers:
// headers.add('Webscale', 'is cool'); // returns header values.
//
// Adding the header 'Webscale': 'is cool' without preserving any existing
// header values:
// headers.set('Webscale', 'is cool'); // returns header values.
//
// Removing the 'Webscale' completely:
// headers.remove('Webscale');
class Headers {
#headers = {};
#toGeneric = null;
#toCloudProvider = null;
constructor(incomingHeaders, toGeneric, toCloudProvider) {
this.#toGeneric = toGeneric || this.#toWebscaleHeaders;
this.#toCloudProvider = toCloudProvider || this.#fromWebscaleHeaders;
this.#headers = this.#toGeneric(incomingHeaders);
}
// Allows iteration over an instance of the class. See the example above
// for syntax.
[Symbol.iterator]() {
let index = 0;
const entries = Object.entries(this.#headers);
return {
next: () => {
if (index < entries.length) {
return {
value: entries[index++],
done: false,
};
} else {
return {
done: true,
};
}
}
}
}
// Returns the header values of a particular header as an array.
get(name) {
return this.#headers[name.toLowerCase()];
}
// Adds a string value to a header. Header names are case insensitive.
// Existing header values are preserved. Returns the updated header values
// as an array.
add(name, value) {
if (this.#headers[name.toLowerCase()]) {
this.#headers[name.toLowerCase()].push(value);
} else {
this.#headers[name.toLowerCase()] = [value];
}
return this.get(name);
}
// Sets a header to the given value. Header names are case insensitive.
// The given value can be a string or an array for duplicate headers.
// Existing header values are removed. Returns the updated header values as
// an array.
set(name, value) {
if (Array.isArray(value)) {
this.#headers[name.toLowerCase()] = value;
} else {
this.#headers[name.toLowerCase()] = [value];
}
return this.get(name);
}
// Removes the given header completely. Returns all headers.
remove(name) {
delete this.#headers[name.toLowerCase()];
}
// Converts Webscale's representation of headers to a cloud provider's
// representation.
toCloudProvider() {
return this.#toCloudProvider(this.#headers);
}
// Default.
//
// Converts Lambda@Edge header format to Webscale's format.
//
// Lambda@Edge format:
// headers: {
// 'header name in lowercase': [{
// key: 'header name in standard case',
// value: 'header value'
// }],
// ...
// },
//
// Webscale format:
// headers: {
// 'header name in standard case':
// ['header value 1', ... 'header value N'],
// }
#toWebscaleHeaders = (headerTypes) => {
let result = {};
for (const headerType in headerTypes) {
headerTypes[headerType].forEach((header) => {
if (result[header['key'].toLowerCase()]) {
result[header['key'].toLowerCase()].push(
header['value'],
);
} else {
result[header['key'].toLowerCase()] =
[header['value']];
}
});
}
return result;
};
// Default.
//
// Converts Webscale's header format to Lambda@Edge's header format.
//
// Webscale format:
// headers: {
// 'header name in standard case':
// ['header value 1', ... 'header value N'],
// }
//
// Lambda@Edge format:
// headers: {
// 'header name in lowercase': [
// {
// key: 'header name in standard case',
// value: 'header value 1',
// }, ...
// {
// key: 'header name in standard case',
// value: 'header value N',
// },
// ],
// ...
// },
#fromWebscaleHeaders = (headerTypes) => {
let result = {};
for (const headerType in headerTypes) {
headerTypes[headerType].forEach((headerValue) => {
if (!headerValue) return;
if (result[headerType.toLowerCase()]) {
result[headerType.toLowerCase()].push(
{
key: headerType,
value: headerValue,
}
);
} else {
result[headerType.toLowerCase()] = [
{
key: headerType,
value: headerValue,
}
];
}
});
}
return result;
};
};
module.exports = {
Headers,
}