@curveball/core
Advanced tools
Comparing version 0.11.2 to 0.11.3-0
@@ -1,81 +0,122 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const http_errors_1 = require("@curveball/http-errors"); | ||
const events_1 = require("events"); | ||
const http_1 = __importDefault(require("http")); | ||
const base_context_1 = __importDefault(require("./base-context")); | ||
const memory_request_1 = __importDefault(require("./memory-request")); | ||
const memory_response_1 = __importDefault(require("./memory-response")); | ||
const not_found_1 = __importDefault(require("./middleware/not-found")); | ||
const http_utils_1 = require("./node/http-utils"); | ||
const request_1 = __importDefault(require("./node/request")); | ||
const response_1 = __importDefault(require("./node/response")); | ||
const pkg = require('../package.json'); | ||
/** | ||
* The middleware-call Symbol is a special symbol that might exist as a | ||
* property on an object. | ||
* | ||
* If it exists, the object can be used as a middleware. | ||
*/ | ||
const middlewareCall = Symbol('middleware-call'); | ||
exports.middlewareCall = middlewareCall; | ||
// Calls a series of middlewares, in order. | ||
async function invokeMiddlewares(ctx, fns) { | ||
if (fns.length === 0) { | ||
return; | ||
(function (factory) { | ||
if (typeof module === "object" && typeof module.exports === "object") { | ||
var v = factory(require, exports); | ||
if (v !== undefined) module.exports = v; | ||
} | ||
let mw; | ||
if (fns[0][middlewareCall] !== undefined) { | ||
mw = fns[0][middlewareCall].bind(fns[0]); | ||
else if (typeof define === "function" && define.amd) { | ||
define(["require", "exports", "@curveball/http-errors", "events", "http", "./base-context", "./memory-request", "./memory-response", "./middleware/not-found", "./node/http-utils", "./node/request", "./node/response"], factory); | ||
} | ||
else { | ||
mw = fns[0]; | ||
} | ||
return mw(ctx, async () => { | ||
await invokeMiddlewares(ctx, fns.slice(1)); | ||
}); | ||
} | ||
exports.invokeMiddlewares = invokeMiddlewares; | ||
class Application extends events_1.EventEmitter { | ||
constructor() { | ||
super(...arguments); | ||
this.middlewares = []; | ||
} | ||
})(function (require, exports) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const http_errors_1 = require("@curveball/http-errors"); | ||
const events_1 = require("events"); | ||
const http_1 = __importDefault(require("http")); | ||
const base_context_1 = __importDefault(require("./base-context")); | ||
const memory_request_1 = __importDefault(require("./memory-request")); | ||
const memory_response_1 = __importDefault(require("./memory-response")); | ||
const not_found_1 = __importDefault(require("./middleware/not-found")); | ||
const http_utils_1 = require("./node/http-utils"); | ||
const request_1 = __importDefault(require("./node/request")); | ||
const response_1 = __importDefault(require("./node/response")); | ||
const pkg = require('../package.json'); | ||
/** | ||
* Add a middleware to the application. | ||
* The middleware-call Symbol is a special symbol that might exist as a | ||
* property on an object. | ||
* | ||
* Middlewares are called in the order they are added. | ||
* If it exists, the object can be used as a middleware. | ||
*/ | ||
use(...middleware) { | ||
this.middlewares.push(...middleware); | ||
const middlewareCall = Symbol('middleware-call'); | ||
exports.middlewareCall = middlewareCall; | ||
// Calls a series of middlewares, in order. | ||
async function invokeMiddlewares(ctx, fns) { | ||
if (fns.length === 0) { | ||
return; | ||
} | ||
let mw; | ||
if (fns[0][middlewareCall] !== undefined) { | ||
mw = fns[0][middlewareCall].bind(fns[0]); | ||
} | ||
else { | ||
mw = fns[0]; | ||
} | ||
return mw(ctx, async () => { | ||
await invokeMiddlewares(ctx, fns.slice(1)); | ||
}); | ||
} | ||
/** | ||
* Handles a single request and calls all middleware. | ||
*/ | ||
async handle(ctx) { | ||
ctx.response.headers.set('Server', 'curveball/' + pkg.version); | ||
ctx.response.type = 'application/hal+json'; | ||
await invokeMiddlewares(ctx, [...this.middlewares, not_found_1.default]); | ||
} | ||
/** | ||
* Starts a HTTP server on the specified port. | ||
*/ | ||
listen(port) { | ||
const server = http_1.default.createServer(this.callback()); | ||
return server.listen(port); | ||
} | ||
/** | ||
* This function is a callback that can be used for Node's http.Server, | ||
* https.Server, or http2.Server. | ||
*/ | ||
callback() { | ||
return async (req, res) => { | ||
exports.invokeMiddlewares = invokeMiddlewares; | ||
class Application extends events_1.EventEmitter { | ||
constructor() { | ||
super(...arguments); | ||
this.middlewares = []; | ||
} | ||
/** | ||
* Add a middleware to the application. | ||
* | ||
* Middlewares are called in the order they are added. | ||
*/ | ||
use(...middleware) { | ||
this.middlewares.push(...middleware); | ||
} | ||
/** | ||
* Handles a single request and calls all middleware. | ||
*/ | ||
async handle(ctx) { | ||
ctx.response.headers.set('Server', 'curveball/' + pkg.version); | ||
ctx.response.type = 'application/hal+json'; | ||
await invokeMiddlewares(ctx, [...this.middlewares, not_found_1.default]); | ||
} | ||
/** | ||
* Starts a HTTP server on the specified port. | ||
*/ | ||
listen(port) { | ||
const server = http_1.default.createServer(this.callback()); | ||
return server.listen(port); | ||
} | ||
/** | ||
* This function is a callback that can be used for Node's http.Server, | ||
* https.Server, or http2.Server. | ||
*/ | ||
callback() { | ||
return async (req, res) => { | ||
try { | ||
const ctx = this.buildContextFromHttp(req, res); | ||
await this.handle(ctx); | ||
// @ts-ignore - not sure why this line fails | ||
http_utils_1.sendBody(res, ctx.response.body); | ||
} | ||
catch (err) { | ||
// tslint:disable:no-console | ||
console.error(err); | ||
if (http_errors_1.isHttpError(err)) { | ||
res.statusCode = err.httpStatus; | ||
} | ||
else { | ||
res.statusCode = 500; | ||
} | ||
res.setHeader('Content-Type', 'text/plain'); | ||
res.end( | ||
// @ts-ignore | ||
'Uncaught exception. No middleware was defined to handle it. We got the following HTTP status: ' + | ||
res.statusCode); | ||
if (this.listenerCount('error')) { | ||
this.emit('error', err); | ||
} | ||
} | ||
}; | ||
} | ||
async subRequest(arg1, path, headers, body = '') { | ||
let request; | ||
if (typeof arg1 === 'string') { | ||
request = new memory_request_1.default(arg1, path, headers, body); | ||
} | ||
else { | ||
request = arg1; | ||
} | ||
const context = new base_context_1.default(request, new memory_response_1.default()); | ||
try { | ||
const ctx = this.buildContextFromHttp(req, res); | ||
await this.handle(ctx); | ||
// @ts-ignore - not sure why this line fails | ||
http_utils_1.sendBody(res, ctx.response.body); | ||
await this.handle(context); | ||
} | ||
@@ -85,58 +126,27 @@ catch (err) { | ||
console.error(err); | ||
if (this.listenerCount('error')) { | ||
this.emit('error', err); | ||
} | ||
if (http_errors_1.isHttpError(err)) { | ||
res.statusCode = err.httpStatus; | ||
context.response.status = err.httpStatus; | ||
} | ||
else { | ||
res.statusCode = 500; | ||
context.response.status = 500; | ||
} | ||
res.setHeader('Content-Type', 'text/plain'); | ||
res.end( | ||
// @ts-ignore | ||
'Uncaught exception. No middleware was defined to handle it. We got the following HTTP status: ' + | ||
res.statusCode); | ||
if (this.listenerCount('error')) { | ||
this.emit('error', err); | ||
} | ||
context.response.body = | ||
'Uncaught exception. No middleware was defined to handle it. We got the following HTTP status: ' + | ||
context.response.status; | ||
} | ||
}; | ||
} | ||
async subRequest(arg1, path, headers, body = '') { | ||
let request; | ||
if (typeof arg1 === 'string') { | ||
request = new memory_request_1.default(arg1, path, headers, body); | ||
return context.response; | ||
} | ||
else { | ||
request = arg1; | ||
/** | ||
* Creates a Context object based on a node.js request and response object. | ||
*/ | ||
buildContextFromHttp(req, res) { | ||
const context = new base_context_1.default(new request_1.default(req), new response_1.default(res)); | ||
return context; | ||
} | ||
const context = new base_context_1.default(request, new memory_response_1.default()); | ||
try { | ||
await this.handle(context); | ||
} | ||
catch (err) { | ||
// tslint:disable:no-console | ||
console.error(err); | ||
if (this.listenerCount('error')) { | ||
this.emit('error', err); | ||
} | ||
if (http_errors_1.isHttpError(err)) { | ||
context.response.status = err.httpStatus; | ||
} | ||
else { | ||
context.response.status = 500; | ||
} | ||
context.response.body = | ||
'Uncaught exception. No middleware was defined to handle it. We got the following HTTP status: ' + | ||
context.response.status; | ||
} | ||
return context.response; | ||
} | ||
/** | ||
* Creates a Context object based on a node.js request and response object. | ||
*/ | ||
buildContextFromHttp(req, res) { | ||
const context = new base_context_1.default(new request_1.default(req), new response_1.default(res)); | ||
return context; | ||
} | ||
} | ||
exports.default = Application; | ||
exports.default = Application; | ||
}); | ||
//# sourceMappingURL=application.js.map |
@@ -1,128 +0,138 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/** | ||
* The Context object encapsulates a single HTTP request. | ||
* | ||
* It has references to the internal request and response object. | ||
*/ | ||
class BaseContext { | ||
constructor(req, res) { | ||
this.request = req; | ||
this.response = res; | ||
this.state = {}; | ||
(function (factory) { | ||
if (typeof module === "object" && typeof module.exports === "object") { | ||
var v = factory(require, exports); | ||
if (v !== undefined) module.exports = v; | ||
} | ||
/** | ||
* The Request path. | ||
* | ||
* Shortcut for request.path | ||
*/ | ||
get path() { | ||
return this.request.path; | ||
else if (typeof define === "function" && define.amd) { | ||
define(["require", "exports"], factory); | ||
} | ||
})(function (require, exports) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/** | ||
* HTTP method | ||
* The Context object encapsulates a single HTTP request. | ||
* | ||
* Shortcut for request.method | ||
* It has references to the internal request and response object. | ||
*/ | ||
get method() { | ||
return this.request.method; | ||
} | ||
/** | ||
* This object contains parsed query string parameters. | ||
* | ||
* This is a shortcut for request.query | ||
*/ | ||
get query() { | ||
return this.request.query; | ||
} | ||
/** | ||
* accepts is used for negotation the Content-Type with a client. | ||
* | ||
* You can pass a content-type, or an array of content-types. | ||
* The Content-Types you provide are a list of types your application | ||
* supports. | ||
* | ||
* This function will then return the best possible type based on the Accept | ||
* header. | ||
* | ||
* If no compatible types are found, this function returns null. | ||
* | ||
* This is a shortcut to request.accepts() | ||
*/ | ||
accepts(...types) { | ||
return this.request.accepts(...types); | ||
} | ||
/** | ||
* HTTP status code. | ||
* | ||
* This is a shortcut for response.status | ||
*/ | ||
get status() { | ||
return this.response.status; | ||
} | ||
/** | ||
* Sets the HTTP response status code. | ||
* | ||
* This is a shortcut for response.status. | ||
*/ | ||
set status(value) { | ||
this.response.status = value; | ||
} | ||
/** | ||
* Sends an informational (1xx status code) response. | ||
* | ||
* This is a shortcut for response.sendInformational() | ||
*/ | ||
sendInformational(status, headers) { | ||
return this.response.sendInformational(status, headers); | ||
} | ||
/** | ||
* Sends a HTTP/2 push. | ||
* | ||
* The passed middleware will be called with a new Context object specific | ||
* for pushes. | ||
* | ||
* This is a shortcut for response.push() | ||
*/ | ||
push(callback) { | ||
return this.response.push(callback); | ||
} | ||
/** | ||
* returns the ip address of the client that's trying to connect. | ||
* | ||
* If 'trustProxy' is set to true, it means the server is running behind a | ||
* proxy, and the X-Forwarded-For header should be parsed instead. | ||
* | ||
* If there was no real HTTP client, this method will return null. | ||
*/ | ||
ip(trustProxy = false) { | ||
if (this.request.ip !== undefined) { | ||
return this.request.ip(trustProxy); | ||
class BaseContext { | ||
constructor(req, res) { | ||
this.request = req; | ||
this.response = res; | ||
this.state = {}; | ||
} | ||
return null; | ||
} | ||
/** | ||
* redirect redirects the response with an optionally provided HTTP status | ||
* code in the first position to the location provided in address. If no status | ||
* is provided, 303 See Other is used. | ||
* | ||
* It is a wrapper method for the underlying Response.redirect function. | ||
* | ||
* @param {(string|number)} addrOrStatus if passed a string, the string will | ||
* be used to set the Location header of the response object and the default status | ||
* of 303 See Other will be used. If a number, an addressed must be passed in the second | ||
* argument. | ||
* @param {string} address If addrOrStatus is passed a status code, this value is | ||
* set as the value of the response's Location header. | ||
*/ | ||
redirect(addrOrStatus, address = '') { | ||
if (typeof (addrOrStatus) === 'number') { | ||
return this.response.redirect(addrOrStatus, address); | ||
/** | ||
* The Request path. | ||
* | ||
* Shortcut for request.path | ||
*/ | ||
get path() { | ||
return this.request.path; | ||
} | ||
else { | ||
return this.response.redirect(addrOrStatus); | ||
/** | ||
* HTTP method | ||
* | ||
* Shortcut for request.method | ||
*/ | ||
get method() { | ||
return this.request.method; | ||
} | ||
/** | ||
* This object contains parsed query string parameters. | ||
* | ||
* This is a shortcut for request.query | ||
*/ | ||
get query() { | ||
return this.request.query; | ||
} | ||
/** | ||
* accepts is used for negotation the Content-Type with a client. | ||
* | ||
* You can pass a content-type, or an array of content-types. | ||
* The Content-Types you provide are a list of types your application | ||
* supports. | ||
* | ||
* This function will then return the best possible type based on the Accept | ||
* header. | ||
* | ||
* If no compatible types are found, this function returns null. | ||
* | ||
* This is a shortcut to request.accepts() | ||
*/ | ||
accepts(...types) { | ||
return this.request.accepts(...types); | ||
} | ||
/** | ||
* HTTP status code. | ||
* | ||
* This is a shortcut for response.status | ||
*/ | ||
get status() { | ||
return this.response.status; | ||
} | ||
/** | ||
* Sets the HTTP response status code. | ||
* | ||
* This is a shortcut for response.status. | ||
*/ | ||
set status(value) { | ||
this.response.status = value; | ||
} | ||
/** | ||
* Sends an informational (1xx status code) response. | ||
* | ||
* This is a shortcut for response.sendInformational() | ||
*/ | ||
sendInformational(status, headers) { | ||
return this.response.sendInformational(status, headers); | ||
} | ||
/** | ||
* Sends a HTTP/2 push. | ||
* | ||
* The passed middleware will be called with a new Context object specific | ||
* for pushes. | ||
* | ||
* This is a shortcut for response.push() | ||
*/ | ||
push(callback) { | ||
return this.response.push(callback); | ||
} | ||
/** | ||
* returns the ip address of the client that's trying to connect. | ||
* | ||
* If 'trustProxy' is set to true, it means the server is running behind a | ||
* proxy, and the X-Forwarded-For header should be parsed instead. | ||
* | ||
* If there was no real HTTP client, this method will return null. | ||
*/ | ||
ip(trustProxy = false) { | ||
if (this.request.ip !== undefined) { | ||
return this.request.ip(trustProxy); | ||
} | ||
return null; | ||
} | ||
/** | ||
* redirect redirects the response with an optionally provided HTTP status | ||
* code in the first position to the location provided in address. If no status | ||
* is provided, 303 See Other is used. | ||
* | ||
* It is a wrapper method for the underlying Response.redirect function. | ||
* | ||
* @param {(string|number)} addrOrStatus if passed a string, the string will | ||
* be used to set the Location header of the response object and the default status | ||
* of 303 See Other will be used. If a number, an addressed must be passed in the second | ||
* argument. | ||
* @param {string} address If addrOrStatus is passed a status code, this value is | ||
* set as the value of the response's Location header. | ||
*/ | ||
redirect(addrOrStatus, address = '') { | ||
if (typeof (addrOrStatus) === 'number') { | ||
return this.response.redirect(addrOrStatus, address); | ||
} | ||
else { | ||
return this.response.redirect(addrOrStatus); | ||
} | ||
} | ||
} | ||
} | ||
exports.default = BaseContext; | ||
exports.default = BaseContext; | ||
}); | ||
//# sourceMappingURL=base-context.js.map |
@@ -1,98 +0,108 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/** | ||
* This method will check the following request headers: | ||
* | ||
* 1. If-Match | ||
* 2. If-None-Match | ||
* 3. If-Modified-Since | ||
* 4. If-Unmodified-Since | ||
* | ||
* To check these headers,v alues for lastModified and etag should be passed. | ||
* | ||
* The result of this function will return a suggested HTTP status. It will | ||
* return | ||
* * '200' if all the preconditions passed. | ||
* * '304' is a 'Not Modified' status should be returned, and | ||
* * '412' if a 'Precondition failed' error should be returned. | ||
*/ | ||
function conditionalCheck(request, lastModified, etag) { | ||
validateETag(etag); | ||
if (request.headers.has('If-Match')) { | ||
return ifMatchCheck(request.headers.get('If-Match'), etag); | ||
(function (factory) { | ||
if (typeof module === "object" && typeof module.exports === "object") { | ||
var v = factory(require, exports); | ||
if (v !== undefined) module.exports = v; | ||
} | ||
if (request.headers.has('If-None-Match')) { | ||
return ifNoneMatchCheck(request.method, request.headers.get('If-None-Match'), etag); | ||
else if (typeof define === "function" && define.amd) { | ||
define(["require", "exports"], factory); | ||
} | ||
if (request.headers.has('If-Modified-Since')) { | ||
return ifModifiedSinceCheck(request.method, request.headers.get('If-Modified-Since'), lastModified); | ||
})(function (require, exports) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/** | ||
* This method will check the following request headers: | ||
* | ||
* 1. If-Match | ||
* 2. If-None-Match | ||
* 3. If-Modified-Since | ||
* 4. If-Unmodified-Since | ||
* | ||
* To check these headers,v alues for lastModified and etag should be passed. | ||
* | ||
* The result of this function will return a suggested HTTP status. It will | ||
* return | ||
* * '200' if all the preconditions passed. | ||
* * '304' is a 'Not Modified' status should be returned, and | ||
* * '412' if a 'Precondition failed' error should be returned. | ||
*/ | ||
function conditionalCheck(request, lastModified, etag) { | ||
validateETag(etag); | ||
if (request.headers.has('If-Match')) { | ||
return ifMatchCheck(request.headers.get('If-Match'), etag); | ||
} | ||
if (request.headers.has('If-None-Match')) { | ||
return ifNoneMatchCheck(request.method, request.headers.get('If-None-Match'), etag); | ||
} | ||
if (request.headers.has('If-Modified-Since')) { | ||
return ifModifiedSinceCheck(request.method, request.headers.get('If-Modified-Since'), lastModified); | ||
} | ||
if (request.headers.has('If-Unmodified-Since')) { | ||
return ifUnmodifiedSinceCheck(request.headers.get('If-Unmodified-Since'), lastModified); | ||
} | ||
return 200; | ||
} | ||
if (request.headers.has('If-Unmodified-Since')) { | ||
return ifUnmodifiedSinceCheck(request.headers.get('If-Unmodified-Since'), lastModified); | ||
} | ||
return 200; | ||
} | ||
exports.conditionalCheck = conditionalCheck; | ||
function ifMatchCheck(header, serverState) { | ||
if (header === '*') { | ||
return serverState !== null ? 200 : 412; | ||
} | ||
const headerTags = header.split(',').map(foo => foo.trim()); | ||
for (const tag of headerTags) { | ||
if (tag === serverState) | ||
return 200; | ||
} | ||
return 412; | ||
} | ||
function ifNoneMatchCheck(method, header, serverState) { | ||
let pass; | ||
if (header === '*') { | ||
pass = serverState === null; | ||
} | ||
else { | ||
exports.conditionalCheck = conditionalCheck; | ||
function ifMatchCheck(header, serverState) { | ||
if (header === '*') { | ||
return serverState !== null ? 200 : 412; | ||
} | ||
const headerTags = header.split(',').map(foo => foo.trim()); | ||
pass = true; | ||
for (const tag of headerTags) { | ||
if (tag === serverState) { | ||
pass = false; | ||
} | ||
if (tag === serverState) | ||
return 200; | ||
} | ||
return 412; | ||
} | ||
if (!pass) { | ||
if (method === 'GET' || method === 'HEAD') { | ||
return 304; | ||
function ifNoneMatchCheck(method, header, serverState) { | ||
let pass; | ||
if (header === '*') { | ||
pass = serverState === null; | ||
} | ||
else { | ||
return 412; | ||
const headerTags = header.split(',').map(foo => foo.trim()); | ||
pass = true; | ||
for (const tag of headerTags) { | ||
if (tag === serverState) { | ||
pass = false; | ||
} | ||
} | ||
} | ||
} | ||
return 200; | ||
} | ||
function ifModifiedSinceCheck(method, header, serverState) { | ||
if (method !== 'GET' && method !== 'HEAD') { | ||
// Only GET and HEAD are supported, everything else is ignored | ||
if (!pass) { | ||
if (method === 'GET' || method === 'HEAD') { | ||
return 304; | ||
} | ||
else { | ||
return 412; | ||
} | ||
} | ||
return 200; | ||
} | ||
if (serverState === null) { | ||
return 200; | ||
function ifModifiedSinceCheck(method, header, serverState) { | ||
if (method !== 'GET' && method !== 'HEAD') { | ||
// Only GET and HEAD are supported, everything else is ignored | ||
return 200; | ||
} | ||
if (serverState === null) { | ||
return 200; | ||
} | ||
const headerDate = new Date(header); | ||
return (serverState.getTime() > headerDate.getTime()) ? 200 : 304; | ||
} | ||
const headerDate = new Date(header); | ||
return (serverState.getTime() > headerDate.getTime()) ? 200 : 304; | ||
} | ||
function ifUnmodifiedSinceCheck(header, serverState) { | ||
// This is not in any spec, but I believe that we should reject requests | ||
// if we don't know that the Last-Modified value is. | ||
if (serverState === null) { | ||
return 412; | ||
function ifUnmodifiedSinceCheck(header, serverState) { | ||
// This is not in any spec, but I believe that we should reject requests | ||
// if we don't know that the Last-Modified value is. | ||
if (serverState === null) { | ||
return 412; | ||
} | ||
const headerDate = new Date(header); | ||
return (serverState.getTime() <= headerDate.getTime()) ? 200 : 412; | ||
} | ||
const headerDate = new Date(header); | ||
return (serverState.getTime() <= headerDate.getTime()) ? 200 : 412; | ||
} | ||
function validateETag(etag) { | ||
if (etag === null) | ||
return; | ||
if (!/^(W\/)?"[\x21\x23-\x7e]+"$/.test(etag)) { | ||
throw new Error('Etags must be valid. Did you forget the double-quotes?'); | ||
function validateETag(etag) { | ||
if (etag === null) | ||
return; | ||
if (!/^(W\/)?"[\x21\x23-\x7e]+"$/.test(etag)) { | ||
throw new Error('Etags must be valid. Did you forget the double-quotes?'); | ||
} | ||
} | ||
} | ||
}); | ||
//# sourceMappingURL=conditional.js.map |
@@ -1,3 +0,13 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
(function (factory) { | ||
if (typeof module === "object" && typeof module.exports === "object") { | ||
var v = factory(require, exports); | ||
if (v !== undefined) module.exports = v; | ||
} | ||
else if (typeof define === "function" && define.amd) { | ||
define(["require", "exports"], factory); | ||
} | ||
})(function (require, exports) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
}); | ||
//# sourceMappingURL=context.js.map |
@@ -1,81 +0,91 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/** | ||
* This method will return true or false if a Request or Response has a | ||
* Content-Type header that matches the argument. | ||
* | ||
* For example, if the Content-Type header has the value: application/hal+json, | ||
* then the arguments will all return true: | ||
* | ||
* * application/hal+json | ||
* * application/json | ||
* * hal+json | ||
* * json | ||
* * application/* | ||
*/ | ||
function is(message, type) { | ||
const messageType = message.type; | ||
// No Content-Type header | ||
if (!messageType) { | ||
return false; | ||
(function (factory) { | ||
if (typeof module === "object" && typeof module.exports === "object") { | ||
var v = factory(require, exports); | ||
if (v !== undefined) module.exports = v; | ||
} | ||
if (type === messageType) { | ||
// Matches application/hal+json | ||
return true; | ||
else if (typeof define === "function" && define.amd) { | ||
define(["require", "exports"], factory); | ||
} | ||
const [mainType, subType] = messageType.split('/', 2); | ||
if (subType === type) { | ||
// Matches hal+json | ||
return true; | ||
} | ||
if (type === mainType + '/*') { | ||
// matches application/* | ||
return true; | ||
} | ||
const subTypeParts = subType.split('+', 2); | ||
if (subTypeParts.length === 2) { | ||
if (subTypeParts[1] === type) { | ||
// Matches 'json' | ||
})(function (require, exports) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/** | ||
* This method will return true or false if a Request or Response has a | ||
* Content-Type header that matches the argument. | ||
* | ||
* For example, if the Content-Type header has the value: application/hal+json, | ||
* then the arguments will all return true: | ||
* | ||
* * application/hal+json | ||
* * application/json | ||
* * hal+json | ||
* * json | ||
* * application/* | ||
*/ | ||
function is(message, type) { | ||
const messageType = message.type; | ||
// No Content-Type header | ||
if (!messageType) { | ||
return false; | ||
} | ||
if (type === messageType) { | ||
// Matches application/hal+json | ||
return true; | ||
} | ||
if (mainType + '/' + subTypeParts[1] === type) { | ||
// matches application/json | ||
const [mainType, subType] = messageType.split('/', 2); | ||
if (subType === type) { | ||
// Matches hal+json | ||
return true; | ||
} | ||
if (type === mainType + '/*') { | ||
// matches application/* | ||
return true; | ||
} | ||
const subTypeParts = subType.split('+', 2); | ||
if (subTypeParts.length === 2) { | ||
if (subTypeParts[1] === type) { | ||
// Matches 'json' | ||
return true; | ||
} | ||
if (mainType + '/' + subTypeParts[1] === type) { | ||
// matches application/json | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
return false; | ||
} | ||
exports.is = is; | ||
/** | ||
* Parses a RFC7240 Prefer header. | ||
* | ||
* It's a naive parser as it assumes a fairly simple subset of | ||
* Prefer. | ||
* | ||
* TODO: Make this parse every possible variation. | ||
*/ | ||
function parsePrefer(header) { | ||
if (!header) { | ||
return {}; | ||
exports.is = is; | ||
/** | ||
* Parses a RFC7240 Prefer header. | ||
* | ||
* It's a naive parser as it assumes a fairly simple subset of | ||
* Prefer. | ||
* | ||
* TODO: Make this parse every possible variation. | ||
*/ | ||
function parsePrefer(header) { | ||
if (!header) { | ||
return {}; | ||
} | ||
const result = {}; | ||
for (const headerItem of splitHeader(header)) { | ||
const [keyValue] = headerItem.split(';'); | ||
const [key, value] = keyValue.split('='); | ||
result[key.toLowerCase()] = value !== undefined ? value : true; | ||
} | ||
return result; | ||
} | ||
const result = {}; | ||
for (const headerItem of splitHeader(header)) { | ||
const [keyValue] = headerItem.split(';'); | ||
const [key, value] = keyValue.split('='); | ||
result[key.toLowerCase()] = value !== undefined ? value : true; | ||
exports.parsePrefer = parsePrefer; | ||
/** | ||
* This function takes a multi-value comma-separated header and splits it | ||
* into multiple headers. | ||
* | ||
* TODO: In the future this function will respect comma's appearing within | ||
* quotes and ignore them. It doesn't right now. | ||
*/ | ||
function splitHeader(header) { | ||
return header.split(',').map(item => item.trim()); | ||
} | ||
return result; | ||
} | ||
exports.parsePrefer = parsePrefer; | ||
/** | ||
* This function takes a multi-value comma-separated header and splits it | ||
* into multiple headers. | ||
* | ||
* TODO: In the future this function will respect comma's appearing within | ||
* quotes and ignore them. It doesn't right now. | ||
*/ | ||
function splitHeader(header) { | ||
return header.split(',').map(item => item.trim()); | ||
} | ||
exports.splitHeader = splitHeader; | ||
exports.splitHeader = splitHeader; | ||
}); | ||
//# sourceMappingURL=header-helpers.js.map |
@@ -1,83 +0,93 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
class Headers { | ||
constructor(headersObj = {}) { | ||
this.store = {}; | ||
for (const key of Object.keys(headersObj)) { | ||
this.set(key, headersObj[key]); | ||
} | ||
(function (factory) { | ||
if (typeof module === "object" && typeof module.exports === "object") { | ||
var v = factory(require, exports); | ||
if (v !== undefined) module.exports = v; | ||
} | ||
/** | ||
* Sets a HTTP header name and value. | ||
*/ | ||
set(name, value) { | ||
// Storing the header name case-insenstive, but we retain the original | ||
// case as well. | ||
this.store[name.toLowerCase()] = [name, value]; | ||
else if (typeof define === "function" && define.amd) { | ||
define(["require", "exports"], factory); | ||
} | ||
/** | ||
* Gets a HTTP header's value. | ||
* | ||
* This function will return null if the header did not exist. If it did | ||
* exist, it will return a string. | ||
* | ||
* If there were multiple headers with the same value, it will join the | ||
* headers with a comma. | ||
*/ | ||
get(name) { | ||
const tuple = this.store[name.toLowerCase()]; | ||
if (tuple === undefined) { | ||
return null; | ||
})(function (require, exports) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
class Headers { | ||
constructor(headersObj = {}) { | ||
this.store = {}; | ||
for (const key of Object.keys(headersObj)) { | ||
this.set(key, headersObj[key]); | ||
} | ||
} | ||
const value = tuple[1]; | ||
if (typeof (value) === 'string') { | ||
return value; | ||
/** | ||
* Sets a HTTP header name and value. | ||
*/ | ||
set(name, value) { | ||
// Storing the header name case-insenstive, but we retain the original | ||
// case as well. | ||
this.store[name.toLowerCase()] = [name, value]; | ||
} | ||
else if (Array.isArray(value)) { | ||
return value.join(', '); | ||
/** | ||
* Gets a HTTP header's value. | ||
* | ||
* This function will return null if the header did not exist. If it did | ||
* exist, it will return a string. | ||
* | ||
* If there were multiple headers with the same value, it will join the | ||
* headers with a comma. | ||
*/ | ||
get(name) { | ||
const tuple = this.store[name.toLowerCase()]; | ||
if (tuple === undefined) { | ||
return null; | ||
} | ||
const value = tuple[1]; | ||
if (typeof (value) === 'string') { | ||
return value; | ||
} | ||
else if (Array.isArray(value)) { | ||
return value.join(', '); | ||
} | ||
else { | ||
return value.toString(); | ||
} | ||
} | ||
else { | ||
return value.toString(); | ||
/** | ||
* Returns true or false depending on if a HTTP header exists. | ||
*/ | ||
has(name) { | ||
return this.store[name.toLowerCase()] !== undefined; | ||
} | ||
} | ||
/** | ||
* Returns true or false depending on if a HTTP header exists. | ||
*/ | ||
has(name) { | ||
return this.store[name.toLowerCase()] !== undefined; | ||
} | ||
/** | ||
* Returns all HTTP headers. | ||
* | ||
* Headernames are lowercased. Values may be either strings or arrays of | ||
* strings or numbers. | ||
*/ | ||
getAll() { | ||
const result = {}; | ||
for (const headerName of Object.keys(this.store)) { | ||
result[headerName] = this.store[headerName][1]; | ||
/** | ||
* Returns all HTTP headers. | ||
* | ||
* Headernames are lowercased. Values may be either strings or arrays of | ||
* strings or numbers. | ||
*/ | ||
getAll() { | ||
const result = {}; | ||
for (const headerName of Object.keys(this.store)) { | ||
result[headerName] = this.store[headerName][1]; | ||
} | ||
return result; | ||
} | ||
return result; | ||
} | ||
/** | ||
* Appends a new header, without removing an old one with the same name. | ||
*/ | ||
append(name, value) { | ||
const lowerName = name.toLowerCase(); | ||
if (this.store[lowerName] === undefined) { | ||
this.store[lowerName] = [name, value]; | ||
return; | ||
/** | ||
* Appends a new header, without removing an old one with the same name. | ||
*/ | ||
append(name, value) { | ||
const lowerName = name.toLowerCase(); | ||
if (this.store[lowerName] === undefined) { | ||
this.store[lowerName] = [name, value]; | ||
return; | ||
} | ||
const oldArray = Array.isArray(this.store[lowerName][1]) ? this.store[lowerName][1] : [this.store[lowerName][1].toString()]; | ||
this.store[lowerName][1] = oldArray.concat(value); | ||
} | ||
const oldArray = Array.isArray(this.store[lowerName][1]) ? this.store[lowerName][1] : [this.store[lowerName][1].toString()]; | ||
this.store[lowerName][1] = oldArray.concat(value); | ||
/** | ||
* Removes a HTTP header | ||
*/ | ||
delete(name) { | ||
delete this.store[name.toLowerCase()]; | ||
} | ||
} | ||
/** | ||
* Removes a HTTP header | ||
*/ | ||
delete(name) { | ||
delete this.store[name.toLowerCase()]; | ||
} | ||
} | ||
exports.Headers = Headers; | ||
exports.default = Headers; | ||
exports.Headers = Headers; | ||
exports.default = Headers; | ||
}); | ||
//# sourceMappingURL=headers.js.map |
@@ -1,2 +0,1 @@ | ||
"use strict"; | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
@@ -12,22 +11,33 @@ if (mod && mod.__esModule) return mod; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const application_1 = __importStar(require("./application")); | ||
exports.Application = application_1.default; | ||
exports.invokeMiddlewares = application_1.invokeMiddlewares; | ||
exports.middlewareCall = application_1.middlewareCall; | ||
const base_context_1 = __importDefault(require("./base-context")); | ||
exports.BaseContext = base_context_1.default; | ||
const headers_1 = __importDefault(require("./headers")); | ||
exports.Headers = headers_1.default; | ||
const memory_request_1 = __importDefault(require("./memory-request")); | ||
exports.MemoryRequest = memory_request_1.default; | ||
const memory_response_1 = __importDefault(require("./memory-response")); | ||
exports.MemoryResponse = memory_response_1.default; | ||
const request_1 = __importDefault(require("./request")); | ||
exports.Request = request_1.default; | ||
const response_1 = __importDefault(require("./response")); | ||
exports.Response = response_1.default; | ||
const conditional_1 = require("./conditional"); | ||
exports.conditionalCheck = conditional_1.conditionalCheck; | ||
exports.default = application_1.default; | ||
(function (factory) { | ||
if (typeof module === "object" && typeof module.exports === "object") { | ||
var v = factory(require, exports); | ||
if (v !== undefined) module.exports = v; | ||
} | ||
else if (typeof define === "function" && define.amd) { | ||
define(["require", "exports", "./application", "./base-context", "./headers", "./memory-request", "./memory-response", "./request", "./response", "./conditional"], factory); | ||
} | ||
})(function (require, exports) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const application_1 = __importStar(require("./application")); | ||
exports.Application = application_1.default; | ||
exports.invokeMiddlewares = application_1.invokeMiddlewares; | ||
exports.middlewareCall = application_1.middlewareCall; | ||
const base_context_1 = __importDefault(require("./base-context")); | ||
exports.BaseContext = base_context_1.default; | ||
const headers_1 = __importDefault(require("./headers")); | ||
exports.Headers = headers_1.default; | ||
const memory_request_1 = __importDefault(require("./memory-request")); | ||
exports.MemoryRequest = memory_request_1.default; | ||
const memory_response_1 = __importDefault(require("./memory-response")); | ||
exports.MemoryResponse = memory_response_1.default; | ||
const request_1 = __importDefault(require("./request")); | ||
exports.Request = request_1.default; | ||
const response_1 = __importDefault(require("./response")); | ||
exports.Response = response_1.default; | ||
const conditional_1 = require("./conditional"); | ||
exports.conditionalCheck = conditional_1.conditionalCheck; | ||
exports.default = application_1.default; | ||
}); | ||
//# sourceMappingURL=index.js.map |
@@ -1,70 +0,80 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const stream_1 = require("stream"); | ||
const headers_1 = require("./headers"); | ||
const request_1 = __importDefault(require("./request")); | ||
class MemoryRequest extends request_1.default { | ||
constructor(method, requestTarget, headers, body = null) { | ||
super(); | ||
this.method = method; | ||
this.requestTarget = requestTarget; | ||
if (headers && headers.get !== undefined) { | ||
this.headers = headers; | ||
} | ||
else { | ||
this.headers = new headers_1.Headers(headers); | ||
} | ||
this.originalBody = body; | ||
// @ts-ignore: Typescript doesn't like null here because it might be | ||
// incompatible with T, but we're ignoring it as it's a good default. | ||
this.body = null; | ||
(function (factory) { | ||
if (typeof module === "object" && typeof module.exports === "object") { | ||
var v = factory(require, exports); | ||
if (v !== undefined) module.exports = v; | ||
} | ||
async rawBody(encoding, limit) { | ||
return this.getBody(encoding); | ||
else if (typeof define === "function" && define.amd) { | ||
define(["require", "exports", "stream", "./headers", "./request"], factory); | ||
} | ||
/** | ||
* getStream returns a Node.js readable stream. | ||
* | ||
* A stream can typically only be read once. | ||
*/ | ||
getStream() { | ||
const s = new stream_1.Readable(); | ||
s.push(this.getBody()); | ||
s.push(null); | ||
return s; | ||
} | ||
getBody(encoding) { | ||
if (!this.originalBody) { | ||
// Memoizing the null case | ||
this.originalBody = ''; | ||
} | ||
if (typeof this.originalBody === 'object' && !(this.originalBody instanceof Buffer)) { | ||
// Memoizing the JSON object case. | ||
this.originalBody = JSON.stringify(this.originalBody); | ||
} | ||
if (this.originalBody instanceof Buffer) { | ||
// The buffer case | ||
if (typeof encoding === 'undefined') { | ||
return this.originalBody; | ||
})(function (require, exports) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const stream_1 = require("stream"); | ||
const headers_1 = require("./headers"); | ||
const request_1 = __importDefault(require("./request")); | ||
class MemoryRequest extends request_1.default { | ||
constructor(method, requestTarget, headers, body = null) { | ||
super(); | ||
this.method = method; | ||
this.requestTarget = requestTarget; | ||
if (headers && headers.get !== undefined) { | ||
this.headers = headers; | ||
} | ||
else { | ||
return this.originalBody.toString(encoding); | ||
this.headers = new headers_1.Headers(headers); | ||
} | ||
this.originalBody = body; | ||
// @ts-ignore: Typescript doesn't like null here because it might be | ||
// incompatible with T, but we're ignoring it as it's a good default. | ||
this.body = null; | ||
} | ||
else { | ||
// The string case | ||
if (typeof encoding === 'undefined') { | ||
return Buffer.from(this.originalBody); | ||
async rawBody(encoding, limit) { | ||
return this.getBody(encoding); | ||
} | ||
/** | ||
* getStream returns a Node.js readable stream. | ||
* | ||
* A stream can typically only be read once. | ||
*/ | ||
getStream() { | ||
const s = new stream_1.Readable(); | ||
s.push(this.getBody()); | ||
s.push(null); | ||
return s; | ||
} | ||
getBody(encoding) { | ||
if (!this.originalBody) { | ||
// Memoizing the null case | ||
this.originalBody = ''; | ||
} | ||
if (typeof this.originalBody === 'object' && !(this.originalBody instanceof Buffer)) { | ||
// Memoizing the JSON object case. | ||
this.originalBody = JSON.stringify(this.originalBody); | ||
} | ||
if (this.originalBody instanceof Buffer) { | ||
// The buffer case | ||
if (typeof encoding === 'undefined') { | ||
return this.originalBody; | ||
} | ||
else { | ||
return this.originalBody.toString(encoding); | ||
} | ||
} | ||
else { | ||
return this.originalBody; | ||
// The string case | ||
if (typeof encoding === 'undefined') { | ||
return Buffer.from(this.originalBody); | ||
} | ||
else { | ||
return this.originalBody; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
exports.MemoryRequest = MemoryRequest; | ||
exports.default = MemoryRequest; | ||
exports.MemoryRequest = MemoryRequest; | ||
exports.default = MemoryRequest; | ||
}); | ||
//# sourceMappingURL=memory-request.js.map |
@@ -1,20 +0,30 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const headers_1 = require("./headers"); | ||
const response_1 = __importDefault(require("./response")); | ||
class MemoryResponse extends response_1.default { | ||
constructor() { | ||
super(); | ||
this.headers = new headers_1.Headers(); | ||
this.status = 200; | ||
// @ts-ignore: Typescript doesn't like null here because it might be | ||
// incompatible with T, but we're ignoring it as it's a good default. | ||
this.body = null; | ||
(function (factory) { | ||
if (typeof module === "object" && typeof module.exports === "object") { | ||
var v = factory(require, exports); | ||
if (v !== undefined) module.exports = v; | ||
} | ||
} | ||
exports.MemoryResponse = MemoryResponse; | ||
exports.default = MemoryResponse; | ||
else if (typeof define === "function" && define.amd) { | ||
define(["require", "exports", "./headers", "./response"], factory); | ||
} | ||
})(function (require, exports) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const headers_1 = require("./headers"); | ||
const response_1 = __importDefault(require("./response")); | ||
class MemoryResponse extends response_1.default { | ||
constructor() { | ||
super(); | ||
this.headers = new headers_1.Headers(); | ||
this.status = 200; | ||
// @ts-ignore: Typescript doesn't like null here because it might be | ||
// incompatible with T, but we're ignoring it as it's a good default. | ||
this.body = null; | ||
} | ||
} | ||
exports.MemoryResponse = MemoryResponse; | ||
exports.default = MemoryResponse; | ||
}); | ||
//# sourceMappingURL=memory-response.js.map |
@@ -1,26 +0,36 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/** | ||
* This middleware simply triggers a 'NotFound' error. | ||
* | ||
* This is a utility middleware that's automatically added to the middleware | ||
* stack to be 'last'. | ||
* | ||
* The purpose of this mw is that if no other middlewares did anything to | ||
* handle a request, we automatically respond with a 404. | ||
*/ | ||
class NoHandler extends Error { | ||
constructor() { | ||
super(); | ||
this.type = 'https://curveballjs.org/errors/no-handler'; | ||
this.title = 'No handler for this request'; | ||
this.detail = 'This server doesn\'t know what to do with your request. Did you make a typo?'; | ||
this.message = this.title; | ||
this.httpStatus = 404; | ||
(function (factory) { | ||
if (typeof module === "object" && typeof module.exports === "object") { | ||
var v = factory(require, exports); | ||
if (v !== undefined) module.exports = v; | ||
} | ||
} | ||
function mw(ctx) { | ||
throw new NoHandler(); | ||
} | ||
exports.default = mw; | ||
else if (typeof define === "function" && define.amd) { | ||
define(["require", "exports"], factory); | ||
} | ||
})(function (require, exports) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/** | ||
* This middleware simply triggers a 'NotFound' error. | ||
* | ||
* This is a utility middleware that's automatically added to the middleware | ||
* stack to be 'last'. | ||
* | ||
* The purpose of this mw is that if no other middlewares did anything to | ||
* handle a request, we automatically respond with a 404. | ||
*/ | ||
class NoHandler extends Error { | ||
constructor() { | ||
super(); | ||
this.type = 'https://curveballjs.org/errors/no-handler'; | ||
this.title = 'No handler for this request'; | ||
this.detail = 'This server doesn\'t know what to do with your request. Did you make a typo?'; | ||
this.message = this.title; | ||
this.httpStatus = 404; | ||
} | ||
} | ||
function mw(ctx) { | ||
throw new NoHandler(); | ||
} | ||
exports.default = mw; | ||
}); | ||
//# sourceMappingURL=not-found.js.map |
@@ -1,41 +0,51 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const stream_1 = __importDefault(require("stream")); | ||
/** | ||
* A type guard to see if a Response object is a HTTP2 response. | ||
*/ | ||
function isHttp2Response(response) { | ||
return response.stream !== undefined; | ||
} | ||
exports.isHttp2Response = isHttp2Response; | ||
function sendBody(res, body) { | ||
if (body === null) { | ||
// @ts-ignore - not sure why this line fails | ||
res.end(); | ||
return; | ||
(function (factory) { | ||
if (typeof module === "object" && typeof module.exports === "object") { | ||
var v = factory(require, exports); | ||
if (v !== undefined) module.exports = v; | ||
} | ||
else if (typeof body === 'string') { | ||
// @ts-ignore - not sure why this line fails | ||
res.end(body); | ||
else if (typeof define === "function" && define.amd) { | ||
define(["require", "exports", "stream"], factory); | ||
} | ||
else if (body instanceof Buffer) { | ||
// @ts-ignore - not sure why this line fails | ||
res.end(body); | ||
})(function (require, exports) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const stream_1 = __importDefault(require("stream")); | ||
/** | ||
* A type guard to see if a Response object is a HTTP2 response. | ||
*/ | ||
function isHttp2Response(response) { | ||
return response.stream !== undefined; | ||
} | ||
else if (body instanceof stream_1.default) { | ||
// @ts-ignore - not sure why this line fails | ||
body.pipe(res); | ||
exports.isHttp2Response = isHttp2Response; | ||
function sendBody(res, body) { | ||
if (body === null) { | ||
// @ts-ignore - not sure why this line fails | ||
res.end(); | ||
return; | ||
} | ||
else if (typeof body === 'string') { | ||
// @ts-ignore - not sure why this line fails | ||
res.end(body); | ||
} | ||
else if (body instanceof Buffer) { | ||
// @ts-ignore - not sure why this line fails | ||
res.end(body); | ||
} | ||
else if (body instanceof stream_1.default) { | ||
// @ts-ignore - not sure why this line fails | ||
body.pipe(res); | ||
} | ||
else if (typeof body === 'object') { | ||
// @ts-ignore - not sure why this line fails | ||
res.end(JSON.stringify(body)); | ||
} | ||
else { | ||
throw new TypeError('Unsupported type for body: ' + typeof body); | ||
} | ||
} | ||
else if (typeof body === 'object') { | ||
// @ts-ignore - not sure why this line fails | ||
res.end(JSON.stringify(body)); | ||
} | ||
else { | ||
throw new TypeError('Unsupported type for body: ' + typeof body); | ||
} | ||
} | ||
exports.sendBody = sendBody; | ||
exports.sendBody = sendBody; | ||
}); | ||
//# sourceMappingURL=http-utils.js.map |
@@ -1,51 +0,61 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const http2_1 = __importDefault(require("http2")); | ||
const http_utils_1 = require("./http-utils"); | ||
/** | ||
* This is a utility for helping with HTTP/2 Push for node servers. | ||
*/ | ||
async function push(stream, pushCtx) { | ||
const requestHeaders = { | ||
':path': pushCtx.request.requestTarget, | ||
...pushCtx.request.headers.getAll(), | ||
}; | ||
let pushStream; | ||
try { | ||
pushStream = await getPushStream(stream, requestHeaders); | ||
(function (factory) { | ||
if (typeof module === "object" && typeof module.exports === "object") { | ||
var v = factory(require, exports); | ||
if (v !== undefined) module.exports = v; | ||
} | ||
catch (err) { | ||
if (err.code === 'ERR_HTTP2_PUSH_DISABLED') { | ||
// HTTP/2 disabled pusing after all | ||
return; | ||
} | ||
throw err; | ||
else if (typeof define === "function" && define.amd) { | ||
define(["require", "exports", "http2", "./http-utils"], factory); | ||
} | ||
pushStream.on('error', err => { | ||
const isRefusedStream = pushStream.rstCode === http2_1.default.constants.NGHTTP2_REFUSED_STREAM; | ||
if (!isRefusedStream) { | ||
throw err; | ||
})(function (require, exports) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const http2_1 = __importDefault(require("http2")); | ||
const http_utils_1 = require("./http-utils"); | ||
/** | ||
* This is a utility for helping with HTTP/2 Push for node servers. | ||
*/ | ||
async function push(stream, pushCtx) { | ||
const requestHeaders = { | ||
':path': pushCtx.request.requestTarget, | ||
...pushCtx.request.headers.getAll(), | ||
}; | ||
let pushStream; | ||
try { | ||
pushStream = await getPushStream(stream, requestHeaders); | ||
} | ||
}); | ||
pushStream.respond({ | ||
':status': 200, | ||
...pushCtx.response.headers.getAll(), | ||
}); | ||
http_utils_1.sendBody(pushStream, pushCtx.response.body); | ||
} | ||
exports.default = push; | ||
function getPushStream(stream, requestHeaders) { | ||
return new Promise((res, rej) => { | ||
stream.pushStream(requestHeaders, (err, pushStream) => { | ||
if (err) { | ||
rej(err); | ||
catch (err) { | ||
if (err.code === 'ERR_HTTP2_PUSH_DISABLED') { | ||
// HTTP/2 disabled pusing after all | ||
return; | ||
} | ||
res(pushStream); | ||
throw err; | ||
} | ||
pushStream.on('error', err => { | ||
const isRefusedStream = pushStream.rstCode === http2_1.default.constants.NGHTTP2_REFUSED_STREAM; | ||
if (!isRefusedStream) { | ||
throw err; | ||
} | ||
}); | ||
}); | ||
} | ||
pushStream.respond({ | ||
':status': 200, | ||
...pushCtx.response.headers.getAll(), | ||
}); | ||
http_utils_1.sendBody(pushStream, pushCtx.response.body); | ||
} | ||
exports.default = push; | ||
function getPushStream(stream, requestHeaders) { | ||
return new Promise((res, rej) => { | ||
stream.pushStream(requestHeaders, (err, pushStream) => { | ||
if (err) { | ||
rej(err); | ||
return; | ||
} | ||
res(pushStream); | ||
}); | ||
}); | ||
} | ||
}); | ||
//# sourceMappingURL=push.js.map |
@@ -1,90 +0,100 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const raw_body_1 = __importDefault(require("raw-body")); | ||
const headers_1 = require("../headers"); | ||
const request_1 = __importDefault(require("../request")); | ||
class NodeRequest extends request_1.default { | ||
constructor(inner) { | ||
super(); | ||
this.inner = inner; | ||
// @ts-ignore ignoring that headers might be undefined | ||
this.headers = new headers_1.Headers(this.inner.headers); | ||
(function (factory) { | ||
if (typeof module === "object" && typeof module.exports === "object") { | ||
var v = factory(require, exports); | ||
if (v !== undefined) module.exports = v; | ||
} | ||
/** | ||
* HTTP method | ||
* | ||
* For example: GET | ||
*/ | ||
get method() { | ||
return this.inner.method; | ||
else if (typeof define === "function" && define.amd) { | ||
define(["require", "exports", "raw-body", "../headers", "../request"], factory); | ||
} | ||
/** | ||
* The request target. | ||
* | ||
* This contains the literal value after the HTTP method in the request. | ||
* So for: | ||
* | ||
* GET /foo HTTP/1.1 | ||
* | ||
* This would contain '/foo'. In many cases this is the same as the 'path' | ||
* property, but there's 3 other forms in the HTTP specificatio. Here's the | ||
* different formats: | ||
* | ||
* * origin-form - This is the most common. Example: /foo. | ||
* * absolute-form - Clients might sent an entire path. Also used by proxies. | ||
* Example: https://example.org/foo | ||
* * authority-form - Used by the CONNECT method. Example: example.org:1212 | ||
* * asterisk-form - Used by the OPTIONS method. Example: * | ||
* | ||
* In most cases users will want to use the 'path' property instead. only use | ||
* this if you know what you're doing. | ||
* | ||
* @see {@link https://tools.ietf.org/html/rfc7230#section-5.3} | ||
*/ | ||
get requestTarget() { | ||
return this.inner.url; | ||
} | ||
rawBody(encoding, limit) { | ||
const options = {}; | ||
if (limit) { | ||
options.limit = limit; | ||
})(function (require, exports) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const raw_body_1 = __importDefault(require("raw-body")); | ||
const headers_1 = require("../headers"); | ||
const request_1 = __importDefault(require("../request")); | ||
class NodeRequest extends request_1.default { | ||
constructor(inner) { | ||
super(); | ||
this.inner = inner; | ||
// @ts-ignore ignoring that headers might be undefined | ||
this.headers = new headers_1.Headers(this.inner.headers); | ||
} | ||
if (encoding) { | ||
options.encoding = encoding; | ||
/** | ||
* HTTP method | ||
* | ||
* For example: GET | ||
*/ | ||
get method() { | ||
return this.inner.method; | ||
} | ||
const length = this.headers.get('Content-Length'); | ||
if (length) { | ||
options.length = length; | ||
/** | ||
* The request target. | ||
* | ||
* This contains the literal value after the HTTP method in the request. | ||
* So for: | ||
* | ||
* GET /foo HTTP/1.1 | ||
* | ||
* This would contain '/foo'. In many cases this is the same as the 'path' | ||
* property, but there's 3 other forms in the HTTP specificatio. Here's the | ||
* different formats: | ||
* | ||
* * origin-form - This is the most common. Example: /foo. | ||
* * absolute-form - Clients might sent an entire path. Also used by proxies. | ||
* Example: https://example.org/foo | ||
* * authority-form - Used by the CONNECT method. Example: example.org:1212 | ||
* * asterisk-form - Used by the OPTIONS method. Example: * | ||
* | ||
* In most cases users will want to use the 'path' property instead. only use | ||
* this if you know what you're doing. | ||
* | ||
* @see {@link https://tools.ietf.org/html/rfc7230#section-5.3} | ||
*/ | ||
get requestTarget() { | ||
return this.inner.url; | ||
} | ||
return raw_body_1.default(this.inner, options); | ||
} | ||
/** | ||
* getStream returns a Node.js readable stream. | ||
* | ||
* A stream can typically only be read once. | ||
*/ | ||
getStream() { | ||
return this.inner; | ||
} | ||
/** | ||
* Returns the IP address of the HTTP client. | ||
* | ||
* If trustProxy is set to true, it means this server is running behind a | ||
* proxy, and the X-Forwarded-For header should be used instead. | ||
*/ | ||
ip(trustProxy = false) { | ||
if (trustProxy) { | ||
const forwardedForHeader = this.headers.get('X-Forwarded-For'); | ||
if (forwardedForHeader) { | ||
return forwardedForHeader.split(',')[0].trim(); | ||
rawBody(encoding, limit) { | ||
const options = {}; | ||
if (limit) { | ||
options.limit = limit; | ||
} | ||
if (encoding) { | ||
options.encoding = encoding; | ||
} | ||
const length = this.headers.get('Content-Length'); | ||
if (length) { | ||
options.length = length; | ||
} | ||
return raw_body_1.default(this.inner, options); | ||
} | ||
return this.inner.socket.remoteAddress; | ||
/** | ||
* getStream returns a Node.js readable stream. | ||
* | ||
* A stream can typically only be read once. | ||
*/ | ||
getStream() { | ||
return this.inner; | ||
} | ||
/** | ||
* Returns the IP address of the HTTP client. | ||
* | ||
* If trustProxy is set to true, it means this server is running behind a | ||
* proxy, and the X-Forwarded-For header should be used instead. | ||
*/ | ||
ip(trustProxy = false) { | ||
if (trustProxy) { | ||
const forwardedForHeader = this.headers.get('X-Forwarded-For'); | ||
if (forwardedForHeader) { | ||
return forwardedForHeader.split(',')[0].trim(); | ||
} | ||
} | ||
return this.inner.socket.remoteAddress; | ||
} | ||
} | ||
} | ||
exports.NodeRequest = NodeRequest; | ||
exports.default = NodeRequest; | ||
exports.NodeRequest = NodeRequest; | ||
exports.default = NodeRequest; | ||
}); | ||
//# sourceMappingURL=request.js.map |
@@ -1,79 +0,89 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/** | ||
* This is a wrapper around the Node Response object, and handles creates a | ||
* nicer API around Headers access. | ||
*/ | ||
class NodeHeaders { | ||
constructor(inner) { | ||
this.inner = inner; | ||
(function (factory) { | ||
if (typeof module === "object" && typeof module.exports === "object") { | ||
var v = factory(require, exports); | ||
if (v !== undefined) module.exports = v; | ||
} | ||
/** | ||
* Sets a HTTP header name and value | ||
*/ | ||
set(name, value) { | ||
this.inner.setHeader(name, value); | ||
else if (typeof define === "function" && define.amd) { | ||
define(["require", "exports"], factory); | ||
} | ||
})(function (require, exports) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/** | ||
* Gets a HTTP header's value. | ||
* | ||
* This function will return null if the header did not exist. If it did | ||
* exist, it will return a string. | ||
* | ||
* If there were multiple headers with the same value, it will join the | ||
* headers with a comma. | ||
* This is a wrapper around the Node Response object, and handles creates a | ||
* nicer API around Headers access. | ||
*/ | ||
get(name) { | ||
const value = this.inner.getHeader(name); | ||
if (value === undefined || value === null) { | ||
return null; | ||
class NodeHeaders { | ||
constructor(inner) { | ||
this.inner = inner; | ||
} | ||
else if (typeof (value) === 'string') { | ||
return value; | ||
/** | ||
* Sets a HTTP header name and value | ||
*/ | ||
set(name, value) { | ||
this.inner.setHeader(name, value); | ||
} | ||
else if (Array.isArray(value)) { | ||
return value.join(', '); | ||
/** | ||
* Gets a HTTP header's value. | ||
* | ||
* This function will return null if the header did not exist. If it did | ||
* exist, it will return a string. | ||
* | ||
* If there were multiple headers with the same value, it will join the | ||
* headers with a comma. | ||
*/ | ||
get(name) { | ||
const value = this.inner.getHeader(name); | ||
if (value === undefined || value === null) { | ||
return null; | ||
} | ||
else if (typeof (value) === 'string') { | ||
return value; | ||
} | ||
else if (Array.isArray(value)) { | ||
return value.join(', '); | ||
} | ||
else { | ||
return value.toString(); | ||
} | ||
} | ||
else { | ||
return value.toString(); | ||
/** | ||
* Returns true or false depending on if a HTTP header exists. | ||
*/ | ||
has(name) { | ||
return !!this.inner.getHeader(name); | ||
} | ||
} | ||
/** | ||
* Returns true or false depending on if a HTTP header exists. | ||
*/ | ||
has(name) { | ||
return !!this.inner.getHeader(name); | ||
} | ||
/** | ||
* Removes a HTTP header | ||
*/ | ||
delete(name) { | ||
this.inner.removeHeader(name); | ||
} | ||
/** | ||
* Returns all HTTP headers. | ||
* | ||
* Headernames are not lowercased. Values may be either strings or arrays of | ||
* strings. | ||
*/ | ||
getAll() { | ||
// @ts-ignore typescript doesn't like that the getHeaders function can | ||
// have undefined values, so we're just ignoring that problem. | ||
return this.inner.getHeaders(); | ||
} | ||
/** | ||
* Appends a new header, without removing an old one with the same name. | ||
*/ | ||
append(name, value) { | ||
let oldValue = this.inner.getHeader(name); | ||
if (oldValue === undefined) { | ||
oldValue = []; | ||
/** | ||
* Removes a HTTP header | ||
*/ | ||
delete(name) { | ||
this.inner.removeHeader(name); | ||
} | ||
if (!Array.isArray(oldValue)) { | ||
oldValue = [oldValue.toString()]; | ||
/** | ||
* Returns all HTTP headers. | ||
* | ||
* Headernames are not lowercased. Values may be either strings or arrays of | ||
* strings. | ||
*/ | ||
getAll() { | ||
// @ts-ignore typescript doesn't like that the getHeaders function can | ||
// have undefined values, so we're just ignoring that problem. | ||
return this.inner.getHeaders(); | ||
} | ||
this.inner.setHeader(name, oldValue.concat(value)); | ||
/** | ||
* Appends a new header, without removing an old one with the same name. | ||
*/ | ||
append(name, value) { | ||
let oldValue = this.inner.getHeader(name); | ||
if (oldValue === undefined) { | ||
oldValue = []; | ||
} | ||
if (!Array.isArray(oldValue)) { | ||
oldValue = [oldValue.toString()]; | ||
} | ||
this.inner.setHeader(name, oldValue.concat(value)); | ||
} | ||
} | ||
} | ||
exports.default = NodeHeaders; | ||
exports.default = NodeHeaders; | ||
}); | ||
//# sourceMappingURL=response-headers.js.map |
@@ -1,132 +0,142 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const http_1 = __importDefault(require("http")); | ||
const util_1 = require("util"); | ||
const application_1 = require("../application"); | ||
const base_context_1 = __importDefault(require("../base-context")); | ||
const memory_request_1 = __importDefault(require("../memory-request")); | ||
const memory_response_1 = __importDefault(require("../memory-response")); | ||
const response_1 = __importDefault(require("../response")); | ||
const http_utils_1 = require("./http-utils"); | ||
const push_1 = __importDefault(require("./push")); | ||
const response_headers_1 = __importDefault(require("./response-headers")); | ||
class NodeResponse extends response_1.default { | ||
constructor(inner) { | ||
super(); | ||
// The default response status is 404. | ||
this.inner = inner; | ||
// @ts-ignore: Typescript doesn't like null here because it might be | ||
// incompatible with T, but we're ignoring it as it's a good default. | ||
this.body = null; | ||
this.status = 404; | ||
this.explicitStatus = false; | ||
(function (factory) { | ||
if (typeof module === "object" && typeof module.exports === "object") { | ||
var v = factory(require, exports); | ||
if (v !== undefined) module.exports = v; | ||
} | ||
/** | ||
* List of HTTP Headers | ||
*/ | ||
get headers() { | ||
return new response_headers_1.default(this.inner); | ||
else if (typeof define === "function" && define.amd) { | ||
define(["require", "exports", "http", "util", "../application", "../base-context", "../memory-request", "../memory-response", "../response", "./http-utils", "./push", "./response-headers"], factory); | ||
} | ||
/** | ||
* HTTP status code. | ||
*/ | ||
get status() { | ||
return this.inner.statusCode; | ||
} | ||
/** | ||
* Updates the HTTP status code for this response. | ||
*/ | ||
set status(value) { | ||
this.explicitStatus = true; | ||
this.inner.statusCode = value; | ||
} | ||
/** | ||
* Updates the response body. | ||
*/ | ||
set body(value) { | ||
if (!this.explicitStatus) { | ||
// If no status was set earlier, we set it to 200. | ||
this.inner.statusCode = 200; | ||
})(function (require, exports) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const http_1 = __importDefault(require("http")); | ||
const util_1 = require("util"); | ||
const application_1 = require("../application"); | ||
const base_context_1 = __importDefault(require("../base-context")); | ||
const memory_request_1 = __importDefault(require("../memory-request")); | ||
const memory_response_1 = __importDefault(require("../memory-response")); | ||
const response_1 = __importDefault(require("../response")); | ||
const http_utils_1 = require("./http-utils"); | ||
const push_1 = __importDefault(require("./push")); | ||
const response_headers_1 = __importDefault(require("./response-headers")); | ||
class NodeResponse extends response_1.default { | ||
constructor(inner) { | ||
super(); | ||
// The default response status is 404. | ||
this.inner = inner; | ||
// @ts-ignore: Typescript doesn't like null here because it might be | ||
// incompatible with T, but we're ignoring it as it's a good default. | ||
this.body = null; | ||
this.status = 404; | ||
this.explicitStatus = false; | ||
} | ||
this.bodyValue = value; | ||
} | ||
/** | ||
* Returns the response body. | ||
*/ | ||
get body() { | ||
return this.bodyValue; | ||
} | ||
/** | ||
* Sends an informational response before the real response. | ||
* | ||
* This can be used to for example send a `100 Continue` or `103 Early Hints` | ||
* response. | ||
*/ | ||
async sendInformational(status, headers) { | ||
let outHeaders = {}; | ||
if (typeof headers !== 'undefined') { | ||
if (headers.getAll !== undefined) { | ||
outHeaders = headers.getAll(); | ||
/** | ||
* List of HTTP Headers | ||
*/ | ||
get headers() { | ||
return new response_headers_1.default(this.inner); | ||
} | ||
/** | ||
* HTTP status code. | ||
*/ | ||
get status() { | ||
return this.inner.statusCode; | ||
} | ||
/** | ||
* Updates the HTTP status code for this response. | ||
*/ | ||
set status(value) { | ||
this.explicitStatus = true; | ||
this.inner.statusCode = value; | ||
} | ||
/** | ||
* Updates the response body. | ||
*/ | ||
set body(value) { | ||
if (!this.explicitStatus) { | ||
// If no status was set earlier, we set it to 200. | ||
this.inner.statusCode = 200; | ||
} | ||
else { | ||
outHeaders = headers; | ||
} | ||
this.bodyValue = value; | ||
} | ||
/** | ||
* It's a HTTP2 connection. | ||
* Returns the response body. | ||
*/ | ||
if (http_utils_1.isHttp2Response(this.inner)) { | ||
this.inner.stream.additionalHeaders({ | ||
':status': status, | ||
...outHeaders | ||
}); | ||
get body() { | ||
return this.bodyValue; | ||
} | ||
else { | ||
const rawHeaders = []; | ||
for (const headerName of Object.keys(outHeaders)) { | ||
const headerValue = outHeaders[headerName]; | ||
if (Array.isArray(headerValue)) { | ||
for (const headerVal of headerValue) { | ||
rawHeaders.push(`${headerName}: ${headerVal}\r\n`); | ||
} | ||
/** | ||
* Sends an informational response before the real response. | ||
* | ||
* This can be used to for example send a `100 Continue` or `103 Early Hints` | ||
* response. | ||
*/ | ||
async sendInformational(status, headers) { | ||
let outHeaders = {}; | ||
if (typeof headers !== 'undefined') { | ||
if (headers.getAll !== undefined) { | ||
outHeaders = headers.getAll(); | ||
} | ||
else { | ||
rawHeaders.push(`${headerName}: ${headerValue}\r\n`); | ||
outHeaders = headers; | ||
} | ||
} | ||
// @ts-ignore | ||
const writeRaw = util_1.promisify(this.inner._writeRaw.bind(this.inner)); | ||
const message = `HTTP/1.1 ${status} ${http_1.default.STATUS_CODES[status]}\r\n${rawHeaders.join('')}\r\n`; | ||
await writeRaw(message, 'ascii'); | ||
/** | ||
* It's a HTTP2 connection. | ||
*/ | ||
if (http_utils_1.isHttp2Response(this.inner)) { | ||
this.inner.stream.additionalHeaders({ | ||
':status': status, | ||
...outHeaders | ||
}); | ||
} | ||
else { | ||
const rawHeaders = []; | ||
for (const headerName of Object.keys(outHeaders)) { | ||
const headerValue = outHeaders[headerName]; | ||
if (Array.isArray(headerValue)) { | ||
for (const headerVal of headerValue) { | ||
rawHeaders.push(`${headerName}: ${headerVal}\r\n`); | ||
} | ||
} | ||
else { | ||
rawHeaders.push(`${headerName}: ${headerValue}\r\n`); | ||
} | ||
} | ||
// @ts-ignore | ||
const writeRaw = util_1.promisify(this.inner._writeRaw.bind(this.inner)); | ||
const message = `HTTP/1.1 ${status} ${http_1.default.STATUS_CODES[status]}\r\n${rawHeaders.join('')}\r\n`; | ||
await writeRaw(message, 'ascii'); | ||
} | ||
} | ||
} | ||
/** | ||
* Sends a HTTP/2 push. | ||
* | ||
* The passed middleware will be called with a new Context object specific | ||
* for pushes. | ||
*/ | ||
async push(callback) { | ||
if (!http_utils_1.isHttp2Response(this.inner)) { | ||
// Not HTTP2 | ||
return; | ||
/** | ||
* Sends a HTTP/2 push. | ||
* | ||
* The passed middleware will be called with a new Context object specific | ||
* for pushes. | ||
*/ | ||
async push(callback) { | ||
if (!http_utils_1.isHttp2Response(this.inner)) { | ||
// Not HTTP2 | ||
return; | ||
} | ||
const stream = this.inner.stream; | ||
if (!stream.pushAllowed) { | ||
// Client doesn't want pushes | ||
return; | ||
} | ||
const pushCtx = new base_context_1.default(new memory_request_1.default('GET', '|||DELIBERATELY_INVALID|||'), new memory_response_1.default()); | ||
await application_1.invokeMiddlewares(pushCtx, [callback]); | ||
if (pushCtx.request.requestTarget === '|||DELIBERATELY_INVALID|||') { | ||
throw new Error('The "path" must be set in the push context\'s request'); | ||
} | ||
return push_1.default(stream, pushCtx); | ||
} | ||
const stream = this.inner.stream; | ||
if (!stream.pushAllowed) { | ||
// Client doesn't want pushes | ||
return; | ||
} | ||
const pushCtx = new base_context_1.default(new memory_request_1.default('GET', '|||DELIBERATELY_INVALID|||'), new memory_response_1.default()); | ||
await application_1.invokeMiddlewares(pushCtx, [callback]); | ||
if (pushCtx.request.requestTarget === '|||DELIBERATELY_INVALID|||') { | ||
throw new Error('The "path" must be set in the push context\'s request'); | ||
} | ||
return push_1.default(stream, pushCtx); | ||
} | ||
} | ||
exports.NodeResponse = NodeResponse; | ||
exports.default = NodeResponse; | ||
exports.NodeResponse = NodeResponse; | ||
exports.default = NodeResponse; | ||
}); | ||
//# sourceMappingURL=response.js.map |
@@ -1,94 +0,104 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const accepts_1 = __importDefault(require("accepts")); | ||
const url_1 = __importDefault(require("url")); | ||
const header_helpers_1 = require("./header-helpers"); | ||
/** | ||
* This interface represents an incoming server request. | ||
*/ | ||
class Request { | ||
/** | ||
* path-part of the request. | ||
* | ||
* For example /hello/world | ||
*/ | ||
get path() { | ||
return url_1.default.parse(this.requestTarget).pathname; | ||
(function (factory) { | ||
if (typeof module === "object" && typeof module.exports === "object") { | ||
var v = factory(require, exports); | ||
if (v !== undefined) module.exports = v; | ||
} | ||
/** | ||
* Sets the request path | ||
*/ | ||
set path(value) { | ||
this.requestTarget = value; | ||
else if (typeof define === "function" && define.amd) { | ||
define(["require", "exports", "accepts", "url", "./header-helpers"], factory); | ||
} | ||
})(function (require, exports) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const accepts_1 = __importDefault(require("accepts")); | ||
const url_1 = __importDefault(require("url")); | ||
const header_helpers_1 = require("./header-helpers"); | ||
/** | ||
* This object contains parsed query parameters. | ||
* This interface represents an incoming server request. | ||
*/ | ||
get query() { | ||
return url_1.default.parse(this.requestTarget, true).query; | ||
} | ||
/** | ||
* Returns the value of the Content-Type header, with any additional | ||
* parameters such as charset= removed. | ||
* | ||
* If there was no Content-Type header, an empty string will be returned. | ||
*/ | ||
get type() { | ||
const type = this.headers.get('content-type'); | ||
if (!type) { | ||
return ''; | ||
class Request { | ||
/** | ||
* path-part of the request. | ||
* | ||
* For example /hello/world | ||
*/ | ||
get path() { | ||
return url_1.default.parse(this.requestTarget).pathname; | ||
} | ||
return type.split(';')[0]; | ||
} | ||
/** | ||
* accepts is used for negotation the Content-Type with a client. | ||
* | ||
* You can pass a content-type, or an array of content-types. | ||
* The Content-Types you provide are a list of types your application | ||
* supports. | ||
* | ||
* This function will then return the best possible type based on the Accept | ||
* header. | ||
* | ||
* If no compatible types are found, this function returns null. | ||
*/ | ||
accepts(...types) { | ||
const mockRequestObj = { | ||
headers: { | ||
accept: this.headers.get('Accept') | ||
/** | ||
* Sets the request path | ||
*/ | ||
set path(value) { | ||
this.requestTarget = value; | ||
} | ||
/** | ||
* This object contains parsed query parameters. | ||
*/ | ||
get query() { | ||
return url_1.default.parse(this.requestTarget, true).query; | ||
} | ||
/** | ||
* Returns the value of the Content-Type header, with any additional | ||
* parameters such as charset= removed. | ||
* | ||
* If there was no Content-Type header, an empty string will be returned. | ||
*/ | ||
get type() { | ||
const type = this.headers.get('content-type'); | ||
if (!type) { | ||
return ''; | ||
} | ||
}; | ||
const result = accepts_1.default(mockRequestObj).type(types); | ||
return result === false ? null : result; | ||
} | ||
/** | ||
* This method will return true or false if a Request or Response has a | ||
* Content-Type header that matches the argument. | ||
* | ||
* For example, if the Content-Type header has the value: application/hal+json, | ||
* then the arguments will all return true: | ||
* | ||
* * application/hal+json | ||
* * application/json | ||
* * hal+json | ||
* * json | ||
* * application/* | ||
*/ | ||
is(type) { | ||
return header_helpers_1.is(this, type); | ||
} | ||
prefer(preference) { | ||
const prefer = header_helpers_1.parsePrefer(this.headers.get('Prefer')); | ||
const val = prefer[preference]; | ||
if (val === undefined) { | ||
return false; | ||
return type.split(';')[0]; | ||
} | ||
return val; | ||
/** | ||
* accepts is used for negotation the Content-Type with a client. | ||
* | ||
* You can pass a content-type, or an array of content-types. | ||
* The Content-Types you provide are a list of types your application | ||
* supports. | ||
* | ||
* This function will then return the best possible type based on the Accept | ||
* header. | ||
* | ||
* If no compatible types are found, this function returns null. | ||
*/ | ||
accepts(...types) { | ||
const mockRequestObj = { | ||
headers: { | ||
accept: this.headers.get('Accept') | ||
} | ||
}; | ||
const result = accepts_1.default(mockRequestObj).type(types); | ||
return result === false ? null : result; | ||
} | ||
/** | ||
* This method will return true or false if a Request or Response has a | ||
* Content-Type header that matches the argument. | ||
* | ||
* For example, if the Content-Type header has the value: application/hal+json, | ||
* then the arguments will all return true: | ||
* | ||
* * application/hal+json | ||
* * application/json | ||
* * hal+json | ||
* * json | ||
* * application/* | ||
*/ | ||
is(type) { | ||
return header_helpers_1.is(this, type); | ||
} | ||
prefer(preference) { | ||
const prefer = header_helpers_1.parsePrefer(this.headers.get('Prefer')); | ||
const val = prefer[preference]; | ||
if (val === undefined) { | ||
return false; | ||
} | ||
return val; | ||
} | ||
} | ||
} | ||
exports.Request = Request; | ||
exports.default = Request; | ||
exports.Request = Request; | ||
exports.default = Request; | ||
}); | ||
//# sourceMappingURL=request.js.map |
@@ -1,89 +0,99 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const header_helpers_1 = require("./header-helpers"); | ||
/** | ||
* This interface represents an incoming server request. | ||
*/ | ||
class Response { | ||
/** | ||
* Returns the value of the Content-Type header, with any additional | ||
* parameters such as charset= removed. | ||
* | ||
* If there was no Content-Type header, an empty string will be returned. | ||
*/ | ||
get type() { | ||
const type = this.headers.get('content-type'); | ||
if (!type) { | ||
return ''; | ||
} | ||
return type.split(';')[0]; | ||
(function (factory) { | ||
if (typeof module === "object" && typeof module.exports === "object") { | ||
var v = factory(require, exports); | ||
if (v !== undefined) module.exports = v; | ||
} | ||
/** | ||
* Shortcut for setting the Content-Type header. | ||
*/ | ||
set type(value) { | ||
this.headers.set('content-type', value); | ||
else if (typeof define === "function" && define.amd) { | ||
define(["require", "exports", "./header-helpers"], factory); | ||
} | ||
})(function (require, exports) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const header_helpers_1 = require("./header-helpers"); | ||
/** | ||
* Sends an informational response before the real response. | ||
* | ||
* This can be used to for example send a `100 Continue` or `103 Early Hints` | ||
* response. | ||
* This interface represents an incoming server request. | ||
*/ | ||
async sendInformational(status, headers) { | ||
// No need to do anything | ||
} | ||
/** | ||
* Sends a HTTP/2 push. | ||
* | ||
* The passed middleware will be called with a new Context object specific | ||
* for pushes. | ||
*/ | ||
async push(callback) { | ||
// Don't do anything | ||
} | ||
/** | ||
* This method will return true or false if a Request or Response has a | ||
* Content-Type header that matches the argument. | ||
* | ||
* For example, if the Content-Type header has the value: application/hal+json, | ||
* then the arguments will all return true: | ||
* | ||
* * application/hal+json | ||
* * application/json | ||
* * hal+json | ||
* * json | ||
* * application/* | ||
*/ | ||
is(type) { | ||
return header_helpers_1.is(this, type); | ||
} | ||
/** | ||
* redirect redirects the response with an optionally provided HTTP status | ||
* code in the first position to the location provided in address. If no status | ||
* is provided, 303 See Other is used. | ||
* | ||
* @param {(string|number)} addrOrStatus if passed a string, the string will | ||
* be used to set the Location header of the response object and the default status | ||
* of 303 See Other will be used. If a number, an addressed must be passed in the second | ||
* argument. | ||
* @param {string} address If addrOrStatus is passed a status code, this value is | ||
* set as the value of the response's Location header. | ||
*/ | ||
redirect(addrOrStatus, address = '') { | ||
let status = 303; | ||
let addr; | ||
if (typeof (addrOrStatus) === 'number') { | ||
status = addrOrStatus; | ||
addr = address; | ||
class Response { | ||
/** | ||
* Returns the value of the Content-Type header, with any additional | ||
* parameters such as charset= removed. | ||
* | ||
* If there was no Content-Type header, an empty string will be returned. | ||
*/ | ||
get type() { | ||
const type = this.headers.get('content-type'); | ||
if (!type) { | ||
return ''; | ||
} | ||
return type.split(';')[0]; | ||
} | ||
else { | ||
addr = addrOrStatus; | ||
/** | ||
* Shortcut for setting the Content-Type header. | ||
*/ | ||
set type(value) { | ||
this.headers.set('content-type', value); | ||
} | ||
this.status = status; | ||
this.headers.set('Location', addr); | ||
/** | ||
* Sends an informational response before the real response. | ||
* | ||
* This can be used to for example send a `100 Continue` or `103 Early Hints` | ||
* response. | ||
*/ | ||
async sendInformational(status, headers) { | ||
// No need to do anything | ||
} | ||
/** | ||
* Sends a HTTP/2 push. | ||
* | ||
* The passed middleware will be called with a new Context object specific | ||
* for pushes. | ||
*/ | ||
async push(callback) { | ||
// Don't do anything | ||
} | ||
/** | ||
* This method will return true or false if a Request or Response has a | ||
* Content-Type header that matches the argument. | ||
* | ||
* For example, if the Content-Type header has the value: application/hal+json, | ||
* then the arguments will all return true: | ||
* | ||
* * application/hal+json | ||
* * application/json | ||
* * hal+json | ||
* * json | ||
* * application/* | ||
*/ | ||
is(type) { | ||
return header_helpers_1.is(this, type); | ||
} | ||
/** | ||
* redirect redirects the response with an optionally provided HTTP status | ||
* code in the first position to the location provided in address. If no status | ||
* is provided, 303 See Other is used. | ||
* | ||
* @param {(string|number)} addrOrStatus if passed a string, the string will | ||
* be used to set the Location header of the response object and the default status | ||
* of 303 See Other will be used. If a number, an addressed must be passed in the second | ||
* argument. | ||
* @param {string} address If addrOrStatus is passed a status code, this value is | ||
* set as the value of the response's Location header. | ||
*/ | ||
redirect(addrOrStatus, address = '') { | ||
let status = 303; | ||
let addr; | ||
if (typeof (addrOrStatus) === 'number') { | ||
status = addrOrStatus; | ||
addr = address; | ||
} | ||
else { | ||
addr = addrOrStatus; | ||
} | ||
this.status = status; | ||
this.headers.set('Location', addr); | ||
} | ||
} | ||
} | ||
exports.Response = Response; | ||
exports.default = Response; | ||
exports.Response = Response; | ||
exports.default = Response; | ||
}); | ||
//# sourceMappingURL=response.js.map |
{ | ||
"name": "@curveball/core", | ||
"version": "0.11.2", | ||
"version": "0.11.3-0", | ||
"description": "Curveball is a framework writting in Typescript for Node.js", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
130844
2415