nestjs / nest

A progressive Node.js framework for building efficient, scalable, and enterprise-grade server-side applications with TypeScript/JavaScript šŸš€
https://nestjs.com
MIT License
67.28k stars 7.59k forks source link

Method handler ${methodName} for /${protoName}/${protoService}/${methodName} expected but not provided #1430

Closed PhilipMantrov closed 5 years ago

PhilipMantrov commented 5 years ago

I am trying to start using nestjs grpc implementation but not succeed. What am i doing wrong?

I already tried lower first case in methods name in proto (in common nodejs/grpc fix with lowercase first letter works). Tried add method-name in @GrpcMethod annotation. Tried provide AuthModule instead AppModule in bootstrap (maybe problem in lifecycles? or method name changed after compilation?).

Already created support request in stackoverflow, but no one did not answer me. https://stackoverflow.com/questions/54008644/method-handler-methodname-for-protoname-protoservice-methodname-exp

I'm submitting a...


[ ] Regression 
[ ] Bug report
[ ] Feature request
[ ] Documentation issue or request
[x] Support request

Current behavior

npm run start

evodesk-auth-nest-grpc@0.0.1 start C:\git\grpc-microservices\evodesk-auth
ts-node -r tsconfig-paths/register src/main.ts

[Nest] 6032   - 2019-1-2 17:30:41   [NestFactory] Starting Nest application...
[Nest] 6032   - 2019-1-2 17:30:41   [InstanceLoader] AppModule dependencies initialized +6ms
[Nest] 6032   - 2019-1-2 17:30:41   [InstanceLoader] AuthModule dependencies initialized +1ms
[Nest] 6032   - 2019-1-2 17:30:41   [NestMicroservice] Nest microservice successfully started +155ms
Method handler signJWT for /EvodeskAuth.Auth/signJWT expected but not provided
Method handler verifyJWT for /EvodeskAuth.Auth/verifyJWT expected but not provided

Minimal reproduction of the problem with instructions

evodesk-auth.proto

syntax = "proto3";
package EvodeskAuth;

service Auth {
    rpc signJWT(SignJWTRequest) returns (SignJWTResponse) {}
    rpc verifyJWT(JWTRequest) returns (VerifyJWTResponse) {}
}

message Error {
    int32 code = 1;
    string message = 2;
}

message Account {
    string _id = 1;
    string login = 2;
    string password = 3;
    string role = 4;
}

message SignJWTRequest {
    string login = 1;
    string password = 2;
}

message SignJWTResponse {
    string jwt = 1;
    Error error = 2;
}

message JWTRequest {
    string jwt = 1;
}

message VerifyJWTResponse {
    bool allow = 1;
    Error error = 2;
}

message JWTObject {
    Account account = 1;
}

auth.controller.ts

@Controller()
export class AuthController {
  @GrpcMethod('EvodeskAuth')
  signJWT(request: EvodeskAuth.SignJWTRequest): Observable<EvodeskAuth.SignJWTResponse> {
    return Observable.create((observer) => {
      MongoDB.collection('accounts').findOne(
        { login: request.login },
        (err: MongoError, result: EvodeskAuth.Account) => {
          if (request.password === result.password) {
            sign({ account: result }, secretKey, { expiresIn: '10s' }, (jwtError: Error, encoded: string) => {
              observer.next({ jwt: encoded });
              observer.complete();
            });
          }
        });
    });
  }

  @GrpcMethod('EvodeskAuth')
  verifyJWT(request: EvodeskAuth.JWTRequest) {
    return Observable.create((observer) => {
      verify(request.jwt, secretKey, (jwtErr: Error, decoded: EvodeskAuth.JWTObject) => {
        if (jwtErr) {
          observer.next({ allow: false, error: { code: 403, message: jwtErr.message } });
        } else {
          MongoDB.collection('accounts').findOne(
            { _id: decoded.account._id },
            (err: MongoError, result: EvodeskAuth.Account) => {
              if (decoded.account.password === result.password) {
                observer.next({ allow: true });
                observer.complete();
              }
            });
        }
      });
    });
  }
}

auth.module.ts

@Module({
  imports: [],
  controllers: [AuthController],
})
export class AuthModule {}

app.module.ts

@Module({
  imports: [AuthModule],
})
export class AppModule {} 

main.ts

async function bootstrap() {
  const app = await NestFactory.createMicroservice(AppModule, {
    transport: Transport.GRPC,
    options: {
      package: 'EvodeskAuth',
      protoPath: join(__dirname, 'evodesk-definitions/proto/evodesk-auth.proto'),
    },
  });
  await MongoClient.connect(dbUrl, (err, client) => {
    MongoDB = client.db(dbName);
  });
  await app.listenAsync();
}
bootstrap(); 

Environment


Nest version: 5.5.0

For Tooling issues:
- Node version: v9.6.1
- Platform:  Windows            
PhilipMantrov commented 5 years ago

Resolved. Problem was in @GrpcMethod('EvodeskAuth'), should be @GrpcMethod('Auth'), because i need to provide Service not a Package.

lock[bot] commented 5 years ago

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.