@flexent/http-server (英语)
状态:α. 积极发展,出新出会打破事物.
最小 Http 服务器,基于 网间网络。 。 。 .
要点
- 最小抽象度高于本地API
- ++可编译处理器
- * 包括(但未执行)标准处理人员
使用量
处理器
应用逻辑在HTTP处理器中被执行. 每个处理器处理其子集域,代表通过调用下()处理给其他人.
export class FooHandler extends HttpHandler {
async handle(ctx: HttpContext, next: HttpNext) {
// Call next() to execute the next middleware in chain.
// Or assign ctx.status and ctx.responseBody to end request processing
}
}
处理器可以从 async (ctx: HttpContext, next: HttpNext) => Promise<void> 函数 :
const handler = createHandler(async (ctx: HttpContext, next: HttpNext) => {
ctx.status = 200;
ctx.responseBody = 'Hello, world!';
}); // returns HttpHandler
链条
多个处理器组成了链.
链条也是处理器,因此请求处理可以是分级的.
export class AppHandler extends HttpChain {
@dep() private foo!: FooHandler;
@dep() private bar!: BarHandler;
@dep() private baz!: BarHandler;
handlers = [
this.foo,
this.bar,
this.baz,
];
}
还可以明确建立链条:
const chain = createChain([
this.foo,
this.bar,
this.baz,
]); // returns HttpHandler
Http 服务器
Http 服务器实例会听到请求,并将请求委托给一个处理器.
它的配置使用 createScope 它为每项请求创造了一个新的范围(网格实例)。 默认,它会解决 HttpScope 并授权处理 HttpHandler 从范围.
// Composition root (global scope)
mesh.service(HttpServer);
mesh.scope(HttpScope);
// Per-request scope
export class HttpScope {
constructor(parent: Mesh) {
super('Http', parent);
this.service(HttpHandler, MyHandler);
}
}
或者,可以直接在组成根中创建范围:
mesh.service(HttpServer);
mesh.scope('HttpScope', () => {
const mesh = new Mesh('Http', mesh);
mesh.service(HttpHandler, MyHandler);
return mesh;
});
请求范围
大多数应用需要请求范围状态。 譬如说, AuthHandler 可以建立呼叫者的身份(例如通过读取信头、饼干、解析JWT等),并将此身份保存在 AuthContext 其他操作人员可以使用.
这样的话, AuthContext 并且其所有受抚养人都将被请求范围(即每个请求一个实例). 网格有助于这种范围界定.
一个最小的例子:
// scoped/AuthContext.ts
export class AuthContext {
principal: User | null = null;
setPrincipal(user: User) {
this.user = user;
}
}
// scoped/AuthHandler.ts
export class AuthHandler implements HttpHandler {
@dep() private auth!: AuthContext;
async handle(ctx: HttpContext, next: HttpNext) {
const authorization = ctx.getRequestHeader('Authorization');
const user = await this.authorize(authorization);
this.auth.setPrincipal(user);
await next();
}
}
export class AppHandler extends HttpChain {
@dep() private authHandler!: AuthHandler;
@dep() private fooHandler!: FooHandler;
handlers = [
this.authHandler,
this.fooHandler,
];
}
export class HttpScope extends Mesh {
constructor(parent: Mesh) {
super('Http', parent);
this.service(AuthContext);
this.service(AuthHandler);
this.service(FooHandler);
this.constant(HttpHandler, AppHandler);
}
}
配置
Http 服务器默认支持以下env变量:
- HTTP Port( 默认值: 8080) - 要收听的端口
- HTTP ADADSES( 默认为 0.0. 0.0 ) - 绑定地址
- HTTP TIMEOUT( 默认: 300 000 }) - HTTP 套接字超时
- HTTP SHUTDOWN DELAY( 默认 : 5 000 }) —— 停止接受连接前的睡眠( 用于在 k8s 等环境中的 0- 下行部署)
- HTTP BODY LIMIT (默认: 5 * 1024 * 1024 }) - 请求正文中允许的最大字节数
API 计费表
请求
请求 URL
请求 URL 已解析并可作为本地 URL 对象 :
ctx.url.searchParams;
查询参数
使用 ctx.url.searchParams 访问查询字符串.
或者,使用 ctx.query 是一个 Http 密码。 。 。 .
请求信头
获取请求头值 :
const authorization = ctx.getRequestHeader('Authorization');
请求信头支持多个值,所以存储为 Http 密码。 。 。 .
ctx.requestHeaders; // { 'content-type': ['application/json'], ... }
请求机构
请求体需要明确读取.
const body = await ctx.readRequestBody();
体型推断自 Content-Type 头,但也可以明确指定.
const jsonBody = await ctx.readRequestBody('json');
下列请求体类型得到支持:
jsontexturlencodedraw
回应
身份代码
指定状态代码 :
ctx.status = 500;
状态也可以从标准Middleware所抛出的错误中读取:
class AccessDeniedError extends Error {
status = 403;
override name = this.constructor.name;
}
throw new AccessDeniedError();
答复信头
设置响应头值 :
ctx.setResponseHeader('X-Powered-By', 'My Awesome App');
响应信头支持多个值,因此存储为 Http 密码。 。 。 .
反应机构
设定响应机构 :
ctx.responseBody = {
foo: 123
};
这个 Content-Type 财务报告和审定财务报表 Content-Length 如果不明确预测,则会推断出信头.
支持以下应对机构类型:
- 字符串( 文本/ 平面)
- JSON(应用/json)
- 缓冲(应用/x-octet-stream)
- 流( 默认用块编码接通)
注意: 如果您正在使用缓冲或流线, 您可能希望明确设置 Content- Type .
杂项
Http 密码
请求/响应信头和解析的查询字符串对象支持每个密钥的多个值.
为了向它们提供统一的型号安全访问,它们被储存为 HttpDict 类型,
只不过 Record<string, string[]>。 。 。 .
因此在访问时期望字符串数组 ctx.requestHeaders, (中文(简体) ), ctx.responseHeaders 或者说 ctx.query。 。 。 .
或使用 ctx.getRequestHeader, (中文(简体) ), ctx.setResponseHeader 财务报告和审定财务报表 ctx.url.searchParams 高级API.