Add basic response factories and helpers
This commit is contained in:
parent
3acc1bc83e
commit
a9ffa771dc
10
package-lock.json
generated
10
package-lock.json
generated
@ -98,11 +98,21 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/negotiator": {
|
||||||
|
"version": "0.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/negotiator/-/negotiator-0.6.1.tgz",
|
||||||
|
"integrity": "sha512-c4mvXFByghezQ/eVGN5HvH/jI63vm3B7FiE81BUzDAWmuiohRecCO6ddU60dfq29oKUMiQujsoB2h0JQC7JHKA=="
|
||||||
|
},
|
||||||
"dotenv": {
|
"dotenv": {
|
||||||
"version": "8.2.0",
|
"version": "8.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
|
||||||
"integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw=="
|
"integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw=="
|
||||||
},
|
},
|
||||||
|
"negotiator": {
|
||||||
|
"version": "0.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
|
||||||
|
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
|
||||||
|
},
|
||||||
"typescript": {
|
"typescript": {
|
||||||
"version": "4.1.3",
|
"version": "4.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz",
|
||||||
|
@ -10,7 +10,9 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@extollo/di": "file:../di",
|
"@extollo/di": "file:../di",
|
||||||
"@extollo/util": "file:../util",
|
"@extollo/util": "file:../util",
|
||||||
|
"@types/negotiator": "^0.6.1",
|
||||||
"dotenv": "^8.2.0",
|
"dotenv": "^8.2.0",
|
||||||
|
"negotiator": "^0.6.2",
|
||||||
"typescript": "^4.1.3"
|
"typescript": "^4.1.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {},
|
"devDependencies": {},
|
||||||
|
11
src/http/HTTPError.ts
Normal file
11
src/http/HTTPError.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import {ErrorWithContext, HTTPStatus, HTTPMessage} from "@extollo/util"
|
||||||
|
|
||||||
|
export class HTTPError extends ErrorWithContext {
|
||||||
|
constructor(
|
||||||
|
public readonly status: HTTPStatus = 500,
|
||||||
|
public readonly message: string = ''
|
||||||
|
) {
|
||||||
|
super(message || HTTPMessage[status])
|
||||||
|
this.message = message || HTTPMessage[status]
|
||||||
|
}
|
||||||
|
}
|
@ -5,7 +5,7 @@ import {HTTPCookieJar} from "../kernel/HTTPCookieJar";
|
|||||||
import {TLSSocket} from "tls";
|
import {TLSSocket} from "tls";
|
||||||
import * as url from "url";
|
import * as url from "url";
|
||||||
import {Response} from "./Response";
|
import {Response} from "./Response";
|
||||||
import {ActivatedRoute} from "../routing/ActivatedRoute";
|
import * as Negotiator from "negotiator";
|
||||||
|
|
||||||
// FIXME - add others?
|
// FIXME - add others?
|
||||||
export type HTTPMethod = 'post' | 'get' | 'patch' | 'put' | 'delete' | 'unknown';
|
export type HTTPMethod = 'post' | 'get' | 'patch' | 'put' | 'delete' | 'unknown';
|
||||||
@ -41,6 +41,7 @@ export class Request extends ScopedContainer {
|
|||||||
public readonly isXHR: boolean;
|
public readonly isXHR: boolean;
|
||||||
public readonly address: HTTPSourceAddress;
|
public readonly address: HTTPSourceAddress;
|
||||||
public readonly response: Response;
|
public readonly response: Response;
|
||||||
|
public readonly mediaTypes: string[];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected clientRequest: IncomingMessage,
|
protected clientRequest: IncomingMessage,
|
||||||
@ -98,6 +99,7 @@ export class Request extends ScopedContainer {
|
|||||||
port
|
port
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.mediaTypes = (new Negotiator(clientRequest)).mediaTypes()
|
||||||
this.response = new Response(this, serverResponse)
|
this.response = new Response(this, serverResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,10 +117,33 @@ export class Request extends ScopedContainer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// session
|
accepts(type: string) {
|
||||||
// route
|
if ( type === 'json' ) type = 'application/json'
|
||||||
// respond
|
else if ( type === 'xml' ) type = 'application/xml'
|
||||||
// body
|
else if ( type === 'html' ) type = 'text/html'
|
||||||
|
|
||||||
|
type = type.toLowerCase()
|
||||||
|
|
||||||
|
const possible = [
|
||||||
|
type,
|
||||||
|
type.split('/')[0] + '/*',
|
||||||
|
'*/*'
|
||||||
|
]
|
||||||
|
|
||||||
|
return this.mediaTypes.some(media => possible.includes(media.toLowerCase()))
|
||||||
|
}
|
||||||
|
|
||||||
|
wants(): 'html' | 'json' | 'xml' | 'unknown' {
|
||||||
|
const jsonIdx = this.mediaTypes.indexOf('application/json') ?? this.mediaTypes.indexOf('application/*') ?? this.mediaTypes.indexOf('*/*')
|
||||||
|
const xmlIdx = this.mediaTypes.indexOf('application/xml') ?? this.mediaTypes.indexOf('application/*') ?? this.mediaTypes.indexOf('*/*')
|
||||||
|
const htmlIdx = this.mediaTypes.indexOf('text/html') ?? this.mediaTypes.indexOf('text/*') ?? this.mediaTypes.indexOf('*/*')
|
||||||
|
|
||||||
|
if ( htmlIdx >= 0 && htmlIdx <= jsonIdx && htmlIdx <= xmlIdx ) return 'html'
|
||||||
|
if ( jsonIdx >= 0 && jsonIdx <= htmlIdx && jsonIdx <= xmlIdx ) return 'json'
|
||||||
|
if ( xmlIdx >= 0 && xmlIdx <= jsonIdx && xmlIdx <= htmlIdx ) return 'xml'
|
||||||
|
return 'unknown'
|
||||||
|
}
|
||||||
|
|
||||||
// hostname
|
// hostname
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -127,8 +152,7 @@ export class Request extends ScopedContainer {
|
|||||||
fresh/stale - cache
|
fresh/stale - cache
|
||||||
remote ips (proxy)
|
remote ips (proxy)
|
||||||
signedCookies
|
signedCookies
|
||||||
accepts content type, charsets, encodings, languages
|
accepts charsets, encodings, languages
|
||||||
is content type (wants)
|
|
||||||
range header parser
|
range header parser
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
20
src/http/response/DehydratedStateResponseFactory.ts
Normal file
20
src/http/response/DehydratedStateResponseFactory.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import {ResponseFactory} from "./ResponseFactory"
|
||||||
|
import {Rehydratable} from "@extollo/util"
|
||||||
|
import {Request} from "../lifecycle/Request";
|
||||||
|
|
||||||
|
export function dehydrate(value: Rehydratable): DehydratedStateResponseFactory {
|
||||||
|
return new DehydratedStateResponseFactory(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DehydratedStateResponseFactory extends ResponseFactory {
|
||||||
|
constructor(
|
||||||
|
public readonly rehydratable: Rehydratable
|
||||||
|
) { super() }
|
||||||
|
|
||||||
|
public async write(request: Request) {
|
||||||
|
request = await super.write(request)
|
||||||
|
request.response.body = JSON.stringify(this.rehydratable.dehydrate())
|
||||||
|
request.response.setHeader('Content-Type', 'application/json')
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
}
|
90
src/http/response/ErrorResponseFactory.ts
Normal file
90
src/http/response/ErrorResponseFactory.ts
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
import {ResponseFactory} from "./ResponseFactory"
|
||||||
|
import {ErrorWithContext, HTTPStatus} from "@extollo/util"
|
||||||
|
import {Request} from "../lifecycle/Request";
|
||||||
|
import * as api from "./api"
|
||||||
|
|
||||||
|
export function error(
|
||||||
|
error: Error | string,
|
||||||
|
status: HTTPStatus = HTTPStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
output: 'json' | 'html' | 'auto' = 'auto'
|
||||||
|
): ErrorResponseFactory {
|
||||||
|
if ( typeof error === 'string' ) error = new Error(error)
|
||||||
|
return new ErrorResponseFactory(error, status, output)
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ErrorResponseFactory extends ResponseFactory {
|
||||||
|
protected targetMode: 'json' | 'html' | 'auto' = 'auto'
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public readonly error: Error,
|
||||||
|
status: HTTPStatus,
|
||||||
|
output: 'json' | 'html' | 'auto' = 'auto'
|
||||||
|
) {
|
||||||
|
super()
|
||||||
|
this.status(status)
|
||||||
|
this.mode(output)
|
||||||
|
}
|
||||||
|
|
||||||
|
public mode(output: 'json' | 'html' | 'auto'): ErrorResponseFactory {
|
||||||
|
this.targetMode = output
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
public async write(request: Request) {
|
||||||
|
request = await super.write(request)
|
||||||
|
const wants = request.wants()
|
||||||
|
|
||||||
|
if ( this.targetMode === 'json' || (this.targetMode === 'auto' && wants === 'json') ) {
|
||||||
|
request.response.setHeader('Content-Type', 'application/json')
|
||||||
|
request.response.body = this.buildJSON(this.error)
|
||||||
|
} else if ( this.targetMode === 'html' || (this.targetMode === 'auto' && (wants === 'html' || wants === 'unknown')) ) {
|
||||||
|
request.response.setHeader('Content-Type', 'text/html')
|
||||||
|
request.response.body = this.buildHTML(this.error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME XML support
|
||||||
|
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the HTML display for the given error.
|
||||||
|
* @param {Error} error
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected buildHTML(error: Error) {
|
||||||
|
let context: any
|
||||||
|
if ( error instanceof ErrorWithContext ) {
|
||||||
|
context = error.context
|
||||||
|
if ( error.originalError ) {
|
||||||
|
error = error.originalError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let str = `
|
||||||
|
<b>Sorry, an unexpected error occurred while processing your request.</b>
|
||||||
|
<br>
|
||||||
|
<pre><code>
|
||||||
|
Name: ${error.name}
|
||||||
|
Message: ${error.message}
|
||||||
|
Stack trace:
|
||||||
|
- ${error.stack ? error.stack.split(/\s+at\s+/).slice(1).join('<br> - ') : 'none'}
|
||||||
|
</code></pre>
|
||||||
|
`
|
||||||
|
|
||||||
|
if ( context && typeof context === 'object' ) {
|
||||||
|
str += `
|
||||||
|
<pre><code>
|
||||||
|
Context:
|
||||||
|
${Object.keys(context).map(key => ` - ${key} : ${context[key]}`)}
|
||||||
|
</code></pre>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
protected buildJSON(error: Error) {
|
||||||
|
return JSON.stringify(api.error(error))
|
||||||
|
}
|
||||||
|
}
|
19
src/http/response/HTMLResponseFactory.ts
Normal file
19
src/http/response/HTMLResponseFactory.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import {ResponseFactory} from "./ResponseFactory";
|
||||||
|
import {Request} from "../lifecycle/Request";
|
||||||
|
|
||||||
|
export function html(value: string): HTMLResponseFactory {
|
||||||
|
return new HTMLResponseFactory(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
export class HTMLResponseFactory extends ResponseFactory {
|
||||||
|
constructor(
|
||||||
|
public readonly value: string,
|
||||||
|
) { super() }
|
||||||
|
|
||||||
|
public async write(request: Request) {
|
||||||
|
request = await super.write(request)
|
||||||
|
request.response.setHeader('Content-Type', 'text/html; charset=utf-8')
|
||||||
|
request.response.body = this.value
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
}
|
16
src/http/response/HTTPErrorResponseFactory.ts
Normal file
16
src/http/response/HTTPErrorResponseFactory.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import {ErrorResponseFactory} from "./ErrorResponseFactory";
|
||||||
|
import {HTTPError} from "../HTTPError";
|
||||||
|
import {HTTPStatus} from "@extollo/util"
|
||||||
|
|
||||||
|
export function http(status: HTTPStatus, message?: string, output: 'json' | 'html' | 'auto' = 'auto'): HTTPErrorResponseFactory {
|
||||||
|
return new HTTPErrorResponseFactory(new HTTPError(status, message), output)
|
||||||
|
}
|
||||||
|
|
||||||
|
export class HTTPErrorResponseFactory extends ErrorResponseFactory {
|
||||||
|
constructor(
|
||||||
|
public readonly error: HTTPError,
|
||||||
|
output: 'json' | 'html' | 'auto' = 'auto', // FIXME xml support
|
||||||
|
) {
|
||||||
|
super(error, error.status, output)
|
||||||
|
}
|
||||||
|
}
|
19
src/http/response/JSONResponseFactory.ts
Normal file
19
src/http/response/JSONResponseFactory.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import {ResponseFactory} from "./ResponseFactory";
|
||||||
|
import {Request} from "../lifecycle/Request";
|
||||||
|
|
||||||
|
export function json(value: any): JSONResponseFactory {
|
||||||
|
return new JSONResponseFactory(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
export class JSONResponseFactory extends ResponseFactory {
|
||||||
|
constructor(
|
||||||
|
public readonly value: any
|
||||||
|
) { super() }
|
||||||
|
|
||||||
|
public async write(request: Request) {
|
||||||
|
request = await super.write(request)
|
||||||
|
request.response.setHeader('Content-Type', 'application/json')
|
||||||
|
request.response.body = JSON.stringify(this.value)
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
}
|
17
src/http/response/ResponseFactory.ts
Normal file
17
src/http/response/ResponseFactory.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import {HTTPStatus} from "@extollo/util"
|
||||||
|
import {Instantiable} from "@extollo/di"
|
||||||
|
import {Request} from "../lifecycle/Request"
|
||||||
|
|
||||||
|
export abstract class ResponseFactory {
|
||||||
|
protected targetStatus: HTTPStatus = HTTPStatus.OK
|
||||||
|
|
||||||
|
public async write(request: Request): Promise<Request> {
|
||||||
|
request.response.setStatus(this.targetStatus)
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
|
||||||
|
public status(status: HTTPStatus) {
|
||||||
|
this.targetStatus = status
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
19
src/http/response/StringResponseFactory.ts
Normal file
19
src/http/response/StringResponseFactory.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import {ResponseFactory} from "./ResponseFactory";
|
||||||
|
import {Request} from "../lifecycle/Request";
|
||||||
|
|
||||||
|
export function plaintext(value: string): StringResponseFactory {
|
||||||
|
return new StringResponseFactory(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
export class StringResponseFactory extends ResponseFactory {
|
||||||
|
constructor(
|
||||||
|
public readonly value: string,
|
||||||
|
) { super() }
|
||||||
|
|
||||||
|
public async write(request: Request) {
|
||||||
|
request = await super.write(request)
|
||||||
|
request.response.setHeader('Content-Type', 'text/plain')
|
||||||
|
request.response.body = this.value
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
}
|
21
src/http/response/TemporaryRedirectResponseFactory.ts
Normal file
21
src/http/response/TemporaryRedirectResponseFactory.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import {ResponseFactory} from "./ResponseFactory";
|
||||||
|
import {HTTPStatus} from "@extollo/util";
|
||||||
|
import {Request} from "../lifecycle/Request";
|
||||||
|
|
||||||
|
export function redirect(destination: string): TemporaryRedirectResponseFactory {
|
||||||
|
return new TemporaryRedirectResponseFactory(destination)
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TemporaryRedirectResponseFactory extends ResponseFactory {
|
||||||
|
protected targetStatus: HTTPStatus = HTTPStatus.TEMPORARY_REDIRECT
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public readonly destination: string
|
||||||
|
) { super() }
|
||||||
|
|
||||||
|
public async write(request: Request) {
|
||||||
|
request = await super.write(request)
|
||||||
|
request.response.setHeader('Location', this.destination)
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
}
|
76
src/http/response/api.ts
Normal file
76
src/http/response/api.ts
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/**
|
||||||
|
* Base type for an API response format.
|
||||||
|
*/
|
||||||
|
export interface APIResponse {
|
||||||
|
success: boolean,
|
||||||
|
message?: string,
|
||||||
|
data?: any,
|
||||||
|
error?: {
|
||||||
|
name: string,
|
||||||
|
message: string,
|
||||||
|
stack?: string[],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats a mesage as a successful API response.
|
||||||
|
* @param {string} message
|
||||||
|
* @return APIResponse
|
||||||
|
*/
|
||||||
|
export function message(message: string): APIResponse {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats a single record as a successful API response.
|
||||||
|
* @param record
|
||||||
|
* @return APIResponse
|
||||||
|
*/
|
||||||
|
export function one(record: any): APIResponse {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
data: record,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats an array of records as a successful API response.
|
||||||
|
* @param {array} records
|
||||||
|
* @return APIResponse
|
||||||
|
*/
|
||||||
|
export function many(records: any[]): APIResponse {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
data: {
|
||||||
|
records,
|
||||||
|
total: records.length,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats an error message or Error instance as an API response.
|
||||||
|
* @param {string|Error} error
|
||||||
|
* @return APIResponse
|
||||||
|
*/
|
||||||
|
export function error(error: string | Error): APIResponse {
|
||||||
|
if ( typeof error === 'string' ) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: error,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: error.message,
|
||||||
|
error: {
|
||||||
|
name: error.name,
|
||||||
|
message: error.message,
|
||||||
|
stack: error.stack ? error.stack.split(/\s+at\s+/).slice(1) : [],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
src/index.ts
13
src/index.ts
@ -6,6 +6,7 @@ export * from './lifecycle/AppClass'
|
|||||||
export * from './lifecycle/Unit'
|
export * from './lifecycle/Unit'
|
||||||
|
|
||||||
export * from './http/kernel/module/InjectSessionHTTPModule'
|
export * from './http/kernel/module/InjectSessionHTTPModule'
|
||||||
|
export * from './http/kernel/module/MountActivatedRouteHTTPModule'
|
||||||
export * from './http/kernel/module/PersistSessionHTTPModule'
|
export * from './http/kernel/module/PersistSessionHTTPModule'
|
||||||
export * from './http/kernel/module/PoweredByHeaderInjectionHTTPModule'
|
export * from './http/kernel/module/PoweredByHeaderInjectionHTTPModule'
|
||||||
export * from './http/kernel/module/SetSessionCookieHTTPModule'
|
export * from './http/kernel/module/SetSessionCookieHTTPModule'
|
||||||
@ -17,6 +18,17 @@ export * from './http/kernel/HTTPCookieJar'
|
|||||||
export * from './http/lifecycle/Request'
|
export * from './http/lifecycle/Request'
|
||||||
export * from './http/lifecycle/Response'
|
export * from './http/lifecycle/Response'
|
||||||
|
|
||||||
|
export * as api from './http/response/api'
|
||||||
|
export * from './http/response/DehydratedStateResponseFactory'
|
||||||
|
export * from './http/response/ErrorResponseFactory'
|
||||||
|
export * from './http/response/HTMLResponseFactory'
|
||||||
|
export * from './http/response/HTTPErrorResponseFactory'
|
||||||
|
export * from './http/response/JSONResponseFactory'
|
||||||
|
export * from './http/response/ResponseFactory'
|
||||||
|
export * from './http/response/StringResponseFactory'
|
||||||
|
export * from './http/response/TemporaryRedirectResponseFactory'
|
||||||
|
|
||||||
|
export * from './http/routing/ActivatedRoute'
|
||||||
export * from './http/routing/Route'
|
export * from './http/routing/Route'
|
||||||
export * from './http/routing/RouteGroup'
|
export * from './http/routing/RouteGroup'
|
||||||
|
|
||||||
@ -25,6 +37,7 @@ export * from './http/session/SessionFactory'
|
|||||||
export * from './http/session/MemorySession'
|
export * from './http/session/MemorySession'
|
||||||
|
|
||||||
export * from './http/Controller'
|
export * from './http/Controller'
|
||||||
|
export * from './http/HTTPError'
|
||||||
|
|
||||||
export * from './service/Canonical'
|
export * from './service/Canonical'
|
||||||
export * from './service/CanonicalInstantiable'
|
export * from './service/CanonicalInstantiable'
|
||||||
|
@ -33,7 +33,7 @@ export class HTTPServer extends Unit {
|
|||||||
await new Promise<void>((res, rej) => {
|
await new Promise<void>((res, rej) => {
|
||||||
this.server = createServer(this.handler)
|
this.server = createServer(this.handler)
|
||||||
|
|
||||||
this.server.listen(port, undefined, undefined, () => {
|
this.server.listen(port, () => {
|
||||||
this.logging.success(`Server listening on port ${port}. Press ^C to stop.`)
|
this.logging.success(`Server listening on port ${port}. Press ^C to stop.`)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -55,10 +55,8 @@ export class HTTPServer extends Unit {
|
|||||||
public get handler() {
|
public get handler() {
|
||||||
return async (request: IncomingMessage, response: ServerResponse) => {
|
return async (request: IncomingMessage, response: ServerResponse) => {
|
||||||
const extolloReq = new Request(request, response)
|
const extolloReq = new Request(request, response)
|
||||||
|
|
||||||
await this.kernel.handle(extolloReq)
|
await this.kernel.handle(extolloReq)
|
||||||
await extolloReq.response.send('Hi, from Extollo!!')
|
await extolloReq.response.send('Hi, from Extollo!!')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user