kugacz / nj-request-scope

Performant request scope dependency injection for NestJS framework using express server
MIT License
22 stars 7 forks source link

Request Scope Is Empty With Graph #9

Closed pahakrai closed 1 year ago

pahakrai commented 1 year ago

@kugacz Request scope is empty for graphql only works for the RESTful is there any way to update the request scope context. I am currently using the interceptor approach which doesn't seem to be clean


---- Interceptor -------
@Injectable()
export class InterceptorUsingReqScopedProvider implements NestInterceptor {
  constructor(
    private readonly modRef: ModuleRef,
    private readonly contextProvider: ContextProvider
  ) {}

  async intercept(
    context: ExecutionContext,
    next: CallHandler
  ): Promise<Observable<unknown>> {
    const req = this.getRequest(context);
    if (req.baseUrl === '/graphql') {
      this.contextProvider.setRequest(req);
    }
    return next.handle();
  }
---- CONTEXT PROVIDER ------
import { Inject, Injectable, Scope } from '@nestjs/common';
import { Request } from 'express';
import { IncomingHttpHeaders } from 'http';
import { ClientSession } from 'mongodb';
import mongoose from 'mongoose';
import { NJRS_REQUEST, RequestScope } from 'nj-request-scope';

type RESTOrGraphQLRequest = Request;

@Injectable()
@RequestScope()
export class ContextProvider {
  private _request: any;
  private session: ClientSession;
  public headers: IncomingHttpHeaders;

  constructor(
    @Inject(NJRS_REQUEST) private readonly request: RESTOrGraphQLRequest
  ) {
    this._request = this.request; // NOTHING ON REQUEST
    this.headers = request.headers;
  }

  setRequest(request: Request) {
    this._request = request;
  }

  getUser() {
    return this._request.user;
  }

  getWorkspace() {
    return this._request.headers.workspace;
  }
}

--APP GRAPH SETTINGS ON APP MODULE ---
 GraphQLModule.forRootAsync({
      imports: [RequestScopeModule],
      inject: [NJRS_REQUEST],
      driver: ApolloFederationDriver,
      useFactory: (args) => {
        console.log(args);
        return {
          autoSchemaFile: {
            path: path.join(__dirname, 'schema.graphql'),
            federation: 2,
          },
          cors: true,
          context: async ({ req }) => {
            return { req };
          },
        } as GqlModuleOptions;
      },
    })
kugacz commented 1 year ago

Hi @pahakrai. Sorry for the late answer.

It's hard to check what is the problem if I don't see the whole code but I've prepared a working example with graphql: nj-request-scope-graphql.zip based on this sample: https://github.com/nestjs/nest/tree/master/sample/23-graphql-code-first

  1. Unpack the attached file
  2. In extracted folder run:
    npm i
    npm run start
  3. In the browser go to URL: http://localhost:3000/graphql
  4. In the query window put:
    {
    recipe(id: "1") {
    id
    title
    }
    }
  5. Click the "play" button

Please let me know if this example helped you.

pahakrai commented 1 year ago

@kugacz thank you for pointing it out. I dug a little deeper to find it was global prefix setter issue, somehow the prefix for graphql and other restful api requires to be exact to pass information correctly into the request scope but it doesn't have issue with default request injection from nestjs. May be we can use the scope correctly no matter the request type. I am using useGlobalPrefix: true settings in graph configuration in my service and have to update the graph path on gateway server