Commit a465cb4d authored by nanahira's avatar nanahira

use origin IP provided by nest

parent b04a520b
......@@ -14,7 +14,7 @@ import { createServer, Server } from 'http';
import Koa from 'koa';
import KoaBodyParser from 'koa-bodyparser';
import { KoishiMetascanService } from './providers/koishi-metascan.service';
import { KOISHI_MODULE_OPTIONS } from './utility/koishi.constants';
import { KOISHI_MODULE_OPTIONS, KoishiIpSym } from './utility/koishi.constants';
import { KoishiLoggerService } from './providers/koishi-logger.service';
import { KoishiHttpDiscoveryService } from './koishi-http-discovery/koishi-http-discovery.service';
import { Filter, ReplacedContext } from './utility/replaced-context';
......@@ -44,6 +44,10 @@ export class KoishiService
this.baseDir ??= process.cwd();
this.globalInterceptors = this.koishiModuleOptions.globalInterceptors || [];
this.router = new Router();
this._nestKoaTmpInstance.use((ctx, next) => {
ctx.request.ip = ctx.req[KoishiIpSym];
return next();
});
this._nestKoaTmpInstance.use(KoaBodyParser());
this._nestKoaTmpInstance.use(this.router.routes());
this._nestKoaTmpInstance.use(this.router.allowedMethods());
......
......@@ -4,12 +4,17 @@ import { KoishiService } from '../koishi.service';
import { IncomingMessage, ServerResponse } from 'http';
import { Http2ServerRequest, Http2ServerResponse } from 'http2';
import { parse } from 'url';
import { KoishiIpSym } from '../utility/koishi.constants';
export type RequestWithOriginalUrl = IncomingMessage & { originalUrl?: string };
export type RequestExtended = IncomingMessage & {
originalUrl?: string;
ip?: string;
ips?: string[];
};
@Injectable()
export class KoishiMiddleware
implements NestMiddleware<RequestWithOriginalUrl, ServerResponse>
implements NestMiddleware<RequestExtended, ServerResponse>
{
private readonly koaCallback: (
req: IncomingMessage | Http2ServerRequest,
......@@ -19,7 +24,7 @@ export class KoishiMiddleware
this.koaCallback = this.koishi._nestKoaTmpInstance.callback();
}
use(req: RequestWithOriginalUrl, res: ServerResponse, next: NextFunction) {
use(req: RequestExtended, res: ServerResponse, next: NextFunction) {
const exactUrl = req.originalUrl || req.url;
const matchingUrl = parse(exactUrl).pathname || '';
const match = this.koishi.router.match(matchingUrl, req.method);
......@@ -27,6 +32,7 @@ export class KoishiMiddleware
return next();
}
req.url = exactUrl;
req[KoishiIpSym] = req.ip;
return this.koaCallback(req, res);
}
}
......@@ -20,3 +20,5 @@ export interface MetadataArrayMap {
}
export interface MetadataMap {}
export const KoishiIpSym = Symbol('KoishiIpSym');
......@@ -15,7 +15,9 @@ describe('Koishi module in Fastify adapter', () => {
beforeEach(async () => {
const moduleFixture = await testingModule();
app = moduleFixture.createNestApplication<NestFastifyApplication>(
new FastifyAdapter(),
new FastifyAdapter({
trustProxy: true,
}),
);
app.useWebSocketAdapter(new KoishiWsAdapter(app));
await app.init();
......@@ -46,4 +48,21 @@ describe('Koishi module in Fastify adapter', () => {
expect(res.body).toBe('pong');
});
});
it('should response to koishi routes', () => {
koishiApp.router.get('/ip', (ctx) => {
ctx.status = 233;
ctx.body = ctx.ip;
});
return app
.inject({
method: 'GET',
url: '/ip',
headers: { 'x-forwarded-for': '1.1.1.1' },
})
.then((res) => {
expect(res.statusCode).toBe(233);
expect(res.body).toBe('1.1.1.1');
});
});
});
import { KoishiService } from '../src/koishi.service';
import { INestApplication } from '@nestjs/common';
import { KoishiWsAdapter } from '../src/koishi.ws-adapter';
import http from 'http';
import request from 'supertest';
import { Session } from 'koishi';
import { testingModule } from './utility/testing-module';
import { NestExpressApplication } from '@nestjs/platform-express';
describe('Koishi in Nest.js', () => {
let app: INestApplication;
let app: NestExpressApplication;
let koishiApp: KoishiService;
beforeEach(async () => {
const moduleFixture = await testingModule();
app = moduleFixture.createNestApplication();
app = moduleFixture.createNestApplication<NestExpressApplication>();
app.useWebSocketAdapter(new KoishiWsAdapter(app));
app.set('trust proxy', ['loopback']);
await app.init();
koishiApp = app.get(KoishiService);
});
......@@ -43,6 +44,18 @@ describe('Koishi in Nest.js', () => {
.expect('pong');
});
it('should be correct client ip', () => {
koishiApp.router.get('/ip', (ctx) => {
ctx.status = 233;
ctx.body = ctx.ip;
});
return request(app.getHttpServer())
.get('/ip')
.set('X-Forwarded-For', '1.1.1.1')
.expect(233)
.expect('1.1.1.1');
});
it('should register command', () => {
const command = koishiApp.command('echo');
expect(command._usage).toBe('foo');
......
import { Injectable, NotFoundException } from '@nestjs/common';
import { KoishiCommandInterceptor } from '../../src/utility/koishi.interfaces';
import { Argv } from 'koishi';
import { Argv, Context } from 'koishi';
import {
CommandUsage,
OnGuild,
OnPlatform,
PluginDef,
PutOption,
UseCommand,
} from 'koishi-decorators';
......
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