@curveball/core
Advanced tools
Comparing version 0.19.0 to 0.20.0-alpha.0
/// <reference types="node" /> | ||
import { EventEmitter } from 'events'; | ||
import * as http from 'http'; | ||
import * as WebSocket from 'ws'; | ||
import * as net from 'net'; | ||
import { Context } from './context'; | ||
import { HeadersInterface, HeadersObject } from './headers'; | ||
import { HttpCallback, NodeHttpRequest, NodeHttpResponse } from './node/http-utils'; | ||
import Request from './request'; | ||
import Response from './response'; | ||
import * as WebSocket from 'ws'; | ||
import * as net from 'net'; | ||
import { Request as CurveballRequest } from './request'; | ||
import { Response as CurveballResponse } from './response'; | ||
/** | ||
@@ -46,2 +46,13 @@ * The middleware-call Symbol is a special symbol that might exist as a | ||
/** | ||
* Executes a request on the server using the standard browser Request and | ||
* Response objects from the fetch() standard. | ||
* | ||
* Node will probably provide these out of the box in Node 18. If you're on | ||
* an older version, you'll need a polyfill. | ||
* | ||
* A use-case for this is allowing test frameworks to make fetch-like | ||
* requests without actually having to go over the network. | ||
*/ | ||
fetch(request: Request): Promise<Response>; | ||
/** | ||
* Starts a Websocket-only server on the specified port. | ||
@@ -56,4 +67,5 @@ * | ||
/** | ||
* This function is a callback that can be used for Node's http.Server, | ||
* https.Server, or http2.Server. | ||
* Returns a callback that can be used with Node's http.Server, http2.Server, https.Server. | ||
* | ||
* Normally you want to pass this to the constructor of each of these classes. | ||
*/ | ||
@@ -71,4 +83,4 @@ callback(): HttpCallback; | ||
*/ | ||
subRequest(method: string, path: string, headers?: HeadersInterface | HeadersObject, body?: any): Promise<Response>; | ||
subRequest(request: Request): Promise<Response>; | ||
subRequest(method: string, path: string, headers?: HeadersInterface | HeadersObject, body?: any): Promise<CurveballResponse>; | ||
subRequest(request: CurveballRequest): Promise<CurveballResponse>; | ||
/** | ||
@@ -75,0 +87,0 @@ * Creates a Context object based on a node.js request and response object. |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.invokeMiddlewares = exports.middlewareCall = void 0; | ||
const http_errors_1 = require("@curveball/http-errors"); | ||
const events_1 = require("events"); | ||
const http = require("http"); | ||
const WebSocket = require("ws"); | ||
const http_errors_1 = require("@curveball/http-errors"); | ||
const context_1 = require("./context"); | ||
@@ -14,3 +15,3 @@ const memory_request_1 = require("./memory-request"); | ||
const response_1 = require("./node/response"); | ||
const WebSocket = require("ws"); | ||
const fetch_util_1 = require("./fetch-util"); | ||
// eslint-disable-next-line @typescript-eslint/no-var-requires | ||
@@ -77,2 +78,16 @@ const pkg = require('../package.json'); | ||
/** | ||
* Executes a request on the server using the standard browser Request and | ||
* Response objects from the fetch() standard. | ||
* | ||
* Node will probably provide these out of the box in Node 18. If you're on | ||
* an older version, you'll need a polyfill. | ||
* | ||
* A use-case for this is allowing test frameworks to make fetch-like | ||
* requests without actually having to go over the network. | ||
*/ | ||
async fetch(request) { | ||
const response = await this.subRequest(await (0, fetch_util_1.fetchRequestToCurveballRequest)(request, this.origin)); | ||
return (0, fetch_util_1.curveballResponseToFetchResponse)(response); | ||
} | ||
/** | ||
* Starts a Websocket-only server on the specified port. | ||
@@ -100,29 +115,8 @@ * | ||
/** | ||
* This function is a callback that can be used for Node's http.Server, | ||
* https.Server, or http2.Server. | ||
* Returns a callback that can be used with Node's http.Server, http2.Server, https.Server. | ||
* | ||
* Normally you want to pass this to the constructor of each of these classes. | ||
*/ | ||
callback() { | ||
return async (req, res) => { | ||
try { | ||
const ctx = this.buildContextFromHttp(req, res); | ||
await this.handle(ctx); | ||
(0, http_utils_1.sendBody)(res, ctx.response.body); | ||
} | ||
catch (err) { | ||
// eslint-disable-next-line no-console | ||
console.error(err); | ||
if ((0, http_errors_1.isHttpError)(err)) { | ||
res.statusCode = err.httpStatus; | ||
} | ||
else { | ||
res.statusCode = 500; | ||
} | ||
res.setHeader('Content-Type', 'text/plain'); | ||
res.end('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); | ||
} | ||
} | ||
}; | ||
return (0, http_utils_1.nodeHttpServerCallback)(this); | ||
} | ||
@@ -129,0 +123,0 @@ /** |
import { MemoryRequest as CurveballRequest } from './memory-request'; | ||
import { Response as CurveballResponse } from './response'; | ||
export declare function fetchRequestToCurveballRequest(request: Request): Promise<CurveballRequest<unknown>>; | ||
export declare function fetchRequestToCurveballRequest(request: Request, origin: string): Promise<CurveballRequest<unknown>>; | ||
export declare function curveballResponseToFetchResponse(response: CurveballResponse): Promise<Response>; |
@@ -7,3 +7,3 @@ "use strict"; | ||
const stream_1 = require("stream"); | ||
async function fetchRequestToCurveballRequest(request) { | ||
async function fetchRequestToCurveballRequest(request, origin) { | ||
const headers = new headers_1.Headers(); | ||
@@ -20,3 +20,3 @@ // @ts-expect-error apparently our types don't have an 'entries' on headers, but it's there! | ||
headers.set('host', url.host); | ||
return new memory_request_1.MemoryRequest(request.method, relativeUrl, headers, await request.arrayBuffer()); | ||
return new memory_request_1.MemoryRequest(request.method, relativeUrl, origin, headers, await request.arrayBuffer()); | ||
} | ||
@@ -23,0 +23,0 @@ exports.fetchRequestToCurveballRequest = fetchRequestToCurveballRequest; |
@@ -5,2 +5,4 @@ /// <reference types="node" /> | ||
import { Body } from '../response'; | ||
import { Context } from '../context'; | ||
import Application from '../application'; | ||
/** | ||
@@ -18,4 +20,18 @@ * A node.js Http request | ||
export declare function isHttp2Response(response: NodeHttpResponse): response is http2.Http2ServerResponse; | ||
/** | ||
* Returns a callback that can be used with Node's http.Server, http2.Server, https.Server. | ||
* | ||
* Normally you want to pass this to the constructor of each of these classes. | ||
*/ | ||
export declare function nodeHttpServerCallback(app: Application): HttpCallback; | ||
/** | ||
* Emits a 'body' from a Curveball response to a Node HTTP stream/socket | ||
*/ | ||
export declare function sendBody(res: NodeHttpResponse | http2.Http2Stream, body: Body): void; | ||
/** | ||
* This function takes the request and response objects from a Node http, | ||
* https or http2 server and returns a curveball compatible Context. | ||
*/ | ||
export declare function createContextFromNode(req: NodeHttpRequest, res: NodeHttpResponse, origin: string): Context<unknown, unknown>; | ||
/** | ||
* The HttpCallback is the function that is passed as a request listener to | ||
@@ -22,0 +38,0 @@ * node.js's HTTP implementations (http, https, http2). |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.sendBody = exports.isHttp2Response = void 0; | ||
exports.createContextFromNode = exports.sendBody = exports.nodeHttpServerCallback = exports.isHttp2Response = void 0; | ||
const stream_1 = require("stream"); | ||
const context_1 = require("../context"); | ||
const request_1 = require("./request"); | ||
const response_1 = require("./response"); | ||
const http_errors_1 = require("@curveball/http-errors"); | ||
/** | ||
@@ -12,2 +16,36 @@ * A type guard to see if a Response object is a HTTP2 response. | ||
exports.isHttp2Response = isHttp2Response; | ||
/** | ||
* Returns a callback that can be used with Node's http.Server, http2.Server, https.Server. | ||
* | ||
* Normally you want to pass this to the constructor of each of these classes. | ||
*/ | ||
function nodeHttpServerCallback(app) { | ||
return async (req, res) => { | ||
try { | ||
const ctx = createContextFromNode(req, res, app.origin); | ||
await app.handle(ctx); | ||
sendBody(res, ctx.response.body); | ||
} | ||
catch (err) { | ||
// eslint-disable-next-line no-console | ||
console.error(err); | ||
if ((0, http_errors_1.isHttpError)(err)) { | ||
res.statusCode = err.httpStatus; | ||
} | ||
else { | ||
res.statusCode = 500; | ||
} | ||
res.setHeader('Content-Type', 'text/plain'); | ||
res.end('Uncaught exception. No middleware was defined to handle it. We got the following HTTP status: ' + | ||
res.statusCode); | ||
if (app.listenerCount('error')) { | ||
app.emit('error', err); | ||
} | ||
} | ||
}; | ||
} | ||
exports.nodeHttpServerCallback = nodeHttpServerCallback; | ||
/** | ||
* Emits a 'body' from a Curveball response to a Node HTTP stream/socket | ||
*/ | ||
function sendBody(res, body) { | ||
@@ -38,2 +76,11 @@ if (body === null) { | ||
exports.sendBody = sendBody; | ||
/** | ||
* This function takes the request and response objects from a Node http, | ||
* https or http2 server and returns a curveball compatible Context. | ||
*/ | ||
function createContextFromNode(req, res, origin) { | ||
const context = new context_1.Context(new request_1.NodeRequest(req, origin), new response_1.NodeResponse(res, origin)); | ||
return context; | ||
} | ||
exports.createContextFromNode = createContextFromNode; | ||
//# sourceMappingURL=http-utils.js.map |
{ | ||
"name": "@curveball/core", | ||
"version": "0.19.0", | ||
"version": "0.20.0-alpha.0", | ||
"description": "Curveball is a framework writting in Typescript for Node.js", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -56,21 +56,33 @@ Curveball | ||
* [Router](https://github.com/curveball/router). | ||
* [Body Parser](https://github.com/curveball/bodyparser). | ||
* [Controller][controller]. | ||
* [Access Logs](https://github.com/curveball/accesslog). | ||
* [Sessions](https://github.com/curveball/session). | ||
* [Generating application/problem+json responses](https://github.com/curveball/problem). | ||
* [Router](https://github.com/curveball/router) | ||
* [Body Parser](https://github.com/curveball/bodyparser) | ||
* [Controller][controller] | ||
* [Access Logs](https://github.com/curveball/accesslog) | ||
* [Sessions](https://github.com/curveball/session) | ||
* [Generating application/problem+json responses](https://github.com/curveball/problem) | ||
* [CORS](https://github.com/curveball/cors) | ||
* [Hypermedia Links](https://github.com/curveball/links) | ||
* [Server-rendered React support](https://github.com/curveball/react) | ||
* [Serving static files](https://github.com/curveball/static) | ||
* [JSON-Schema validation](https://github.com/curveball/validator) | ||
AWS Lambda support | ||
------------------- | ||
See [aws-lambda](https://github.com/curveball/aws-lambda). | ||
Project status | ||
Authentication | ||
-------------- | ||
The project is currently in beta. It might go through a few more changes, but | ||
the project is mostly stable. It's ready for production. | ||
* [OAuth2](https://github.com/curveball/oauth2) | ||
* [OAuth2 add-on to let regular browsers log in](https://github.com/curveball/browser-to-bearer) | ||
You might like [a12n-server](https://github.com/curveball/a12n-server), a full | ||
OAuth2 authorization server, written in Curveball and works well with the | ||
OAuth2 middleware. | ||
AWS Lambda support / 'Serverless' | ||
--------------------------------- | ||
* [aws-lambda](https://github.com/curveball/aws-lambda). | ||
* [Azure functions](https://github.com/curveball/azure-function) | ||
Doing internal subrequests | ||
@@ -77,0 +89,0 @@ -------------------------- |
@@ -1,4 +0,8 @@ | ||
import { isHttpError } from '@curveball/http-errors'; | ||
import { EventEmitter } from 'events'; | ||
import * as http from 'http'; | ||
import * as WebSocket from 'ws'; | ||
import * as net from 'net'; | ||
import { isHttpError } from '@curveball/http-errors'; | ||
import { Context } from './context'; | ||
@@ -13,11 +17,15 @@ import { HeadersInterface, HeadersObject } from './headers'; | ||
NodeHttpResponse, | ||
sendBody | ||
nodeHttpServerCallback, | ||
} from './node/http-utils'; | ||
import NodeRequest from './node/request'; | ||
import NodeResponse from './node/response'; | ||
import Request from './request'; | ||
import Response from './response'; | ||
import * as WebSocket from 'ws'; | ||
import * as net from 'net'; | ||
import { Request as CurveballRequest } from './request'; | ||
import { Response as CurveballResponse } from './response'; | ||
import { | ||
curveballResponseToFetchResponse, | ||
fetchRequestToCurveballRequest | ||
} from './fetch-util'; | ||
// eslint-disable-next-line @typescript-eslint/no-var-requires | ||
@@ -111,2 +119,21 @@ const pkg = require('../package.json'); | ||
/** | ||
* Executes a request on the server using the standard browser Request and | ||
* Response objects from the fetch() standard. | ||
* | ||
* Node will probably provide these out of the box in Node 18. If you're on | ||
* an older version, you'll need a polyfill. | ||
* | ||
* A use-case for this is allowing test frameworks to make fetch-like | ||
* requests without actually having to go over the network. | ||
*/ | ||
async fetch(request: Request): Promise<Response> { | ||
const response = await this.subRequest( | ||
await fetchRequestToCurveballRequest(request, this.origin) | ||
); | ||
return curveballResponseToFetchResponse(response); | ||
} | ||
/** | ||
* Starts a Websocket-only server on the specified port. | ||
@@ -141,34 +168,10 @@ * | ||
/** | ||
* This function is a callback that can be used for Node's http.Server, | ||
* https.Server, or http2.Server. | ||
* Returns a callback that can be used with Node's http.Server, http2.Server, https.Server. | ||
* | ||
* Normally you want to pass this to the constructor of each of these classes. | ||
*/ | ||
callback(): HttpCallback { | ||
return async ( | ||
req: NodeHttpRequest, | ||
res: NodeHttpResponse | ||
): Promise<void> => { | ||
try { | ||
const ctx = this.buildContextFromHttp(req, res); | ||
await this.handle(ctx); | ||
sendBody(res, ctx.response.body); | ||
} catch (err: any) { | ||
// eslint-disable-next-line no-console | ||
console.error(err); | ||
if (isHttpError(err)) { | ||
res.statusCode = err.httpStatus; | ||
} else { | ||
res.statusCode = 500; | ||
} | ||
res.setHeader('Content-Type', 'text/plain'); | ||
res.end( | ||
'Uncaught exception. No middleware was defined to handle it. We got the following HTTP status: ' + | ||
res.statusCode | ||
); | ||
return nodeHttpServerCallback(this); | ||
if (this.listenerCount('error')) { | ||
this.emit('error', err); | ||
} | ||
} | ||
}; | ||
} | ||
@@ -208,11 +211,11 @@ | ||
body?: any | ||
): Promise<Response>; | ||
async subRequest(request: Request): Promise<Response>; | ||
): Promise<CurveballResponse>; | ||
async subRequest(request: CurveballRequest): Promise<CurveballResponse>; | ||
async subRequest( | ||
arg1: string | Request, | ||
arg1: string | CurveballRequest, | ||
path?: string, | ||
headers?: HeadersInterface | HeadersObject, | ||
body: any = '' | ||
): Promise<Response> { | ||
let request: Request; | ||
): Promise<CurveballResponse> { | ||
let request: CurveballRequest; | ||
@@ -219,0 +222,0 @@ if (typeof arg1 === 'string') { |
@@ -5,2 +5,7 @@ import * as http from 'http'; | ||
import { Body } from '../response'; | ||
import { Context } from '../context'; | ||
import { NodeRequest as CurveballNodeRequest } from './request'; | ||
import { NodeResponse as CurveballNodeResponse } from './response'; | ||
import Application from '../application'; | ||
import { isHttpError } from '@curveball/http-errors'; | ||
@@ -26,2 +31,43 @@ /** | ||
/** | ||
* Returns a callback that can be used with Node's http.Server, http2.Server, https.Server. | ||
* | ||
* Normally you want to pass this to the constructor of each of these classes. | ||
*/ | ||
export function nodeHttpServerCallback(app: Application): HttpCallback { | ||
return async ( | ||
req: NodeHttpRequest, | ||
res: NodeHttpResponse | ||
): Promise<void> => { | ||
try { | ||
const ctx = createContextFromNode(req, res, app.origin); | ||
await app.handle(ctx); | ||
sendBody(res, ctx.response.body as any); | ||
} catch (err: any) { | ||
// eslint-disable-next-line no-console | ||
console.error(err); | ||
if (isHttpError(err)) { | ||
res.statusCode = err.httpStatus; | ||
} else { | ||
res.statusCode = 500; | ||
} | ||
res.setHeader('Content-Type', 'text/plain'); | ||
res.end( | ||
'Uncaught exception. No middleware was defined to handle it. We got the following HTTP status: ' + | ||
res.statusCode | ||
); | ||
if (app.listenerCount('error')) { | ||
app.emit('error', err); | ||
} | ||
} | ||
}; | ||
} | ||
/** | ||
* Emits a 'body' from a Curveball response to a Node HTTP stream/socket | ||
*/ | ||
export function sendBody(res: NodeHttpResponse | http2.Http2Stream, body: Body): void { | ||
@@ -48,3 +94,18 @@ | ||
/** | ||
* This function takes the request and response objects from a Node http, | ||
* https or http2 server and returns a curveball compatible Context. | ||
*/ | ||
export function createContextFromNode(req: NodeHttpRequest, res: NodeHttpResponse, origin:string) { | ||
const context = new Context( | ||
new CurveballNodeRequest(req, origin), | ||
new CurveballNodeResponse(res, origin) | ||
); | ||
return context; | ||
} | ||
/** | ||
* The HttpCallback is the function that is passed as a request listener to | ||
@@ -51,0 +112,0 @@ * node.js's HTTP implementations (http, https, http2). |
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
191998
82
4445
408