Commit ecf63787 authored by nanahira's avatar nanahira

support all koa routes

parent 23d82194
Pipeline #6074 failed with stages
in 1 minute and 40 seconds
import { ModuleMetadata, Provider, Type } from '@nestjs/common';
import { App, Plugin, MaybeArray } from 'koishi';
import { App, MaybeArray, Plugin } from 'koishi';
import { AbstractHttpAdapter } from '@nestjs/core';
const selectors = [
......
import { Injectable, NestMiddleware, OnModuleInit } from '@nestjs/common';
import { NextFunction, Request, Response } from 'express';
import { KoishiService } from './koishi.service';
import { createProxyMiddleware, RequestHandler } from 'http-proxy-middleware';
@Injectable()
export class KoishiMiddleware
implements NestMiddleware<Request, Response>, OnModuleInit {
constructor(private koishi: KoishiService) {}
private proxyMiddleware: RequestHandler;
async onModuleInit() {
this.proxyMiddleware = createProxyMiddleware({
target: `http://localhost:${this.koishi._nestKoaTmpServerPort}`,
ws: true,
logLevel: 'silent',
});
}
use(req: Request, res: Response, next: NextFunction) {
const match = this.koishi.router.match(req.baseUrl, req.method);
if (
!match.route &&
// ws-reverse onebot goes here
!req.header('x-self-id')
) {
return next();
}
return this.proxyMiddleware(req, res, next);
}
}
import {
DynamicModule,
MiddlewareConsumer,
Module,
OnApplicationShutdown,
NestModule,
Provider,
} from '@nestjs/common';
import { ModuleRef } from '@nestjs/core';
import {
KoishiModuleAsyncOptions,
KoishiModuleOptions,
......@@ -17,6 +17,9 @@ import {
KOISHI_CONTEXT_PRIVATE,
KOISHI_MODULE_OPTIONS,
} from './koishi.constants';
import { KoishiMiddleware } from './koishi.middleware';
import { createServer } from 'http';
import { AddressInfo } from 'net';
const koishiContextProvider: Provider = {
provide: KOISHI_CONTEXT,
......@@ -38,10 +41,25 @@ const koishiContextProviderPrivate: Provider = {
@Module({
providers: [
KoishiService,
{
provide: KoishiService,
inject: [KOISHI_MODULE_OPTIONS],
useFactory: async (options: KoishiModuleOptions) => {
const koishi = new KoishiService(options);
koishi._nestKoaTmpServer = createServer(
koishi._nestKoaTmpInstance.callback(),
);
await new Promise<void>((resolve) => {
koishi._nestKoaTmpServer.listen(0, 'localhost', resolve);
});
koishi._nestKoaTmpServerPort = (koishi._nestKoaTmpServer.address() as AddressInfo).port;
return koishi;
},
},
koishiContextProvider,
koishiContextProviderChannel,
koishiContextProviderPrivate,
KoishiMiddleware,
],
exports: [
KoishiService,
......@@ -50,8 +68,10 @@ const koishiContextProviderPrivate: Provider = {
koishiContextProviderPrivate,
],
})
export class KoishiModule implements OnApplicationShutdown {
constructor(private readonly moduleRef: ModuleRef) {}
export class KoishiModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(KoishiMiddleware).forRoutes('*');
}
static register(options: KoishiModuleOptions): DynamicModule {
return {
......@@ -100,9 +120,4 @@ export class KoishiModule implements OnApplicationShutdown {
inject: [options.useExisting || options.useClass],
};
}
async onApplicationShutdown() {
const koishiApp = this.moduleRef.get(KoishiService);
await koishiApp.stop();
}
}
......@@ -3,38 +3,50 @@ import {
Inject,
Injectable,
OnApplicationBootstrap,
OnModuleDestroy,
OnModuleInit,
} from '@nestjs/common';
import { KOISHI_MODULE_OPTIONS } from './koishi.constants';
import { KoishiModuleOptions } from './koishi.interfaces';
import { Server } from 'http';
import Koa from 'koa';
import KoaRouter from '@koa/router';
@Injectable()
export class KoishiService
extends App
implements OnModuleInit, OnApplicationBootstrap {
implements OnModuleInit, OnApplicationBootstrap, OnModuleDestroy {
constructor(
@Inject(KOISHI_MODULE_OPTIONS)
private readonly koishiModuleOptions: KoishiModuleOptions,
) {
super(koishiModuleOptions);
super({
...koishiModuleOptions,
port: 0,
});
this.router = new KoaRouter();
this._nestKoaTmpInstance.use(this.router.routes());
this._nestKoaTmpInstance.use(this.router.allowedMethods());
}
private setHttpServer() {
if (
this.koishiModuleOptions.httpAdapter &&
!this.koishiModuleOptions.port
) {
_nestKoaTmpInstance = new Koa();
_nestKoaTmpServer: Server;
_nestKoaTmpServerPort: number;
private async setHttpServer() {
if (this.koishiModuleOptions.httpAdapter) {
const httpServer: Server = this.koishiModuleOptions.httpAdapter.getHttpServer();
if (httpServer instanceof Server) {
this.logger('app').info('App using Nest HTTP Server.');
this._httpServer = httpServer;
}
} else {
this._httpServer = this._nestKoaTmpServer;
}
}
onModuleInit() {
this.setHttpServer();
async onModuleInit() {
await this.setHttpServer();
if (this.koishiModuleOptions.usePlugins) {
for (const pluginDesc of this.koishiModuleOptions.usePlugins) {
const ctx = pluginDesc.select
......@@ -48,4 +60,11 @@ export class KoishiService
onApplicationBootstrap() {
return this.start();
}
async onModuleDestroy() {
await this.stop();
if (this._nestKoaTmpServer) {
this._nestKoaTmpServer.close();
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment