简体   繁体   English

expressjs逆转控制器中间件错误

[英]expressjs inversify controller middleware error

I'm building a very little rest api using nodejs, express and inversify. 我正在使用nodejs,express和inversify构建一个非常小的rest api。

Here it is my working code: 这是我的工作代码:

index.ts index.ts

 const container = new Container();
 container.bind<interfaces.Controller>(Types.Controller)
          .to(MyController)
          .whenTargetNamed(Targets.Controller.MyController);

 container.bind<Types.Service>(Types.Service)
          .to(MyService)
          .whenTargetNamed(Targets.Services.MyService);


 const server = new InversifyExpressServer(container); 
 const app = server.build();
 app.listen(3000);

mycontroller.ts mycontroller.ts

 @injectable()
 @controller('/api/test')
 export class MyController {

  constructor(@inject(Types.Service) 
                  @named(Targets.Service.MyService) 
                  private MyService: MyService) { }

  @httpGet('/')
  public getCompanies(req: Request, res: Response, next: any): Promise<any[]> 
  {
    console.log('getTestData');
    return this.MyService.fetchAll();
  }
}  

The above code is working fine. 上面的代码工作正常。 The problem comes out when I want to use a middleware to check the auth token. 当我想使用中间件来检查auth令牌时,就会出现问题。

authmiddleware.ts authmiddleware.ts

function authMiddlewareFactory( 
{
  return (config: { role: string }) => 
  {
    return (req: Request, res: Response, next: any): void => 
    {
        const token = getToken(req);
        console.log(token);
        if (token === null) 
        {
            res.status(403).json({ err: 'You are not allowed' });
            return;  
        }
        next();
    }
}

const authMiddleware = authMiddlewareFactory();
export { authMiddleware };

If I use directly the auth middleware directly in the controller I get the 'You are not allowed' message as expected: 如果直接在控制器中直接使用身份验证中间件,则会收到“您不被允许”的消息,如预期的那样:

mycontroller.ts mycontroller.ts

 @httpGet('/')
 public getCompanies(req: Request, res: Response, next: any): Promise<any[]> 
 {
    authMiddleware({ role: "admin" })(req, res, next);
    console.log('getCompanies');
    return this.CompanyService.fetchAll();
 }

But If I use inversify: 但是,如果我使用反转:

import { authMiddleware } from './authmiddleware'

@injectable()
@controller('/api/test', authMiddleware({ role: "admin" }))
export class MyController {
 // same code as before

I got the following error in compilation time: 在编译时出现以下错误:

ERROR: No matching bindings found for serviceIdentifier: 错误:找不到与serviceIdentifier匹配的绑定:
Error: No matching bindings found for serviceIdentifier: 错误:找不到与serviceIdentifier匹配的绑定:
at InversifyExpressServer.resolveMidleware (node_modules/inversify-express-utils/lib/server.js:133:27) at InversifyExpressServer.registerControllers (inversify-express-utils/lib/server.js:106:21) at InversifyExpressServer.build (node_modules/inversify-express-utils/lib/server.js:94:14) at Object. 在InversifyExpressServer.build(node_modules)上的InversifyExpressServer.resolveMidleware(node_modules / inversify-express-utils / lib / server.js:133:27) /inversify-express-utils/lib/server.js:94:14)。 (dist/index.js:52:20) (dist / index.js:52:20)

I assume that I've to declare my middleware in index.ts like I did for the controller and the service. 我假设必须像在控制器和服务中一样在index.ts中声明中间件。 I tried but without successed. 我尝试过但没有成功。

Thanks 谢谢

I'm using the following versions: 我正在使用以下版本:

"inversify": "4.5.2",
"inversify-express-utils": "5.0.0",
"reflect-metadata": "0.1.10",
"chai": "4.0.2",
"@types/chai": "4.0.0",
"@types/supertest": "2.0.2 ",
"supertest": "3.0.0",

I wrote the following quick test: 我编写了以下快速测试:

import "reflect-metadata";
import * as express from "express";
import { expect } from "chai";
import { Container, injectable, inject, named } from "inversify";
import { InversifyExpressServer, interfaces, controller, httpGet } from "inversify-express-utils";
import * as request from "supertest";

interface IMyService {
    fetchAll(): Promise<string[]>;
}

const Types = {
    Service: Symbol.for("Service")
};

const Targets = {
    Service: {
        MyService: "MyService"
    }
};

function authMiddlewareFactory() {
    return (config: { role: string }) => {
        return (req: express.Request, res: express.Response, next: express.NextFunction): void => {
            const token = req.headers["x-auth-token"];
            console.log(token);
            if (token === null) {
                res.status(403).json({ err: "You are not allowed" });
                return;
            }
            next();
        };
    };
}

const authMiddleware = authMiddlewareFactory();

const container = new Container();

@injectable()
class MyService implements IMyService {
    public fetchAll() {
        return Promise.resolve(["Hello", "World"]);
    }
}

@controller("/api/test")
export class MyController {

    constructor(
        @inject(Types.Service)  @named(Targets.Service.MyService) private myService: MyService
    ) { }

    @httpGet("/", authMiddleware({ role: "admin" }))
    public async getCompanies(req: express.Request, res: express.Response, next: express.NextFunction): Promise<string[]> {
        console.log("getTestData");
        return await this.myService.fetchAll();
    }
}

container.bind<MyService>(Types.Service)
         .to(MyService)
         .whenTargetNamed(Targets.Service.MyService);


const server = new InversifyExpressServer(container);
const app = server.build();

request(app)
    .get("/api/test")
    .set("x-auth-token", "Token 1234567890")
    .expect("Content-Type", /json/)
    .expect(200)
    .expect(function(res: any) {
       const b = res.body;
       console.log(b);
       expect(b[0]).eq("Hello");
       expect(b[1]).eq("World");
    })
    .end(function(err, res) {
        if (err) {
            throw err;
        }
    });

It prints the following: 它打印以下内容:

Token 1234567890
getTestData
[ 'Hello', 'World' ]

In inversify-express-utils 5.0.0 (the recommended version right now) you don't need to declare bindings for controllers and you also don't need to decorate controllers with @injectable() . inversify-express-utils 5.0.0(当前推荐的版本)中,您不需要声明控制器的绑定,也不需要用@injectable()装饰控制器。

I created my example using one unique file but in the real application, you will have multiple files. 我使用一个唯一的文件创建了示例,但是在实际应用程序中,您将拥有多个文件。 You need to import your controller one time: 您需要一次导入控制器:

import "./controllers/some_controller";

You can learn more about this at https://github.com/inversify/inversify-express-utils#important-information-about-the-controller-decorator and https://github.com/inversify/inversify-express-utils/releases/tag/5.0.0 . 您可以在https://github.com/inversify/inversify-express-utils#important-information-about-the-controller-decoratorhttps://github.com/inversify/inversify/inversify-express-utils了解更多信息/releases/tag/5.0.0

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM