I have a NestJS application which acts as a proxy between a front-end and multiple other back-ends.
I basically want to be able to pass a specific header (Authorization) from incoming @Req (requests) in the controller to the HttpService that then talks to the other back-ends.
user controller (has access to request) -> user service (injects httpService that somehow already picks the Authorization header) -> External backends.
Right now I need to extract the token from @Headers and then pass token to service which has to paste it to all HttpService calls.
Thanks in advance!
Ok, I managed to solve this by actually using a middleware that I initially thought. I am not a 100% sure this is the NEST way but intercepting the underlying axios reference of the HttpService did the trick:
@Injectable()
export class BearerMiddleware implements NestMiddleware {
constructor(private readonly httpService: HttpService) {}
use(req: Request, res: Response, next: Function) {
this.httpService.axiosRef.interceptors.request.use(request => {
request.headers = {
...request.headers,
Authorization: req.headers.Authorization || '',
};
return request;
});
next();
}
}
I'm not sure if this will help you, but maybe if you get the header from the controller and put it in your services function...
// Controller:
@Get()
getAll(@Request() req){
const header = req.headers;
return this._zoneService.sendToHttp(header);
}
Maybe microservices can be better?
middleware
answer, I have another version using interceptor
:@Injectable()
export class HttpServiceInterceptor implements NestInterceptor {
constructor(private httpService: HttpService) {}
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
// ** if you user normal HTTP module **
const ctx = context.switchToHttp();
const token = ctx.getRequest().headers['authorization'];
// ** if you user GraphQL module **
const ctx = GqlExecutionContext.create(context);
const token = ctx.getContext().token;
if (ctx.token) {
this.httpService.axiosRef.defaults.headers.common['authorization'] =
token;
}
return next.handle().pipe();
}
}
If you use GraphQLModule
, do not forget to pass token to context:
GraphQLModule.forRoot({
debug: true,
playground: true,
autoSchemaFile: 'schema.gql',
context: ({ req }) => {
return { token: req.headers.authorization };
},
}),
The interceptor can be injected into a certain controller:
@UseInterceptors(HttpServiceInterceptor)
export class CatsController {}
or register a global interceptor like following:
@Module({
providers: [
{
provide: APP_INTERCEPTOR,
useClass: HttpServiceInterceptor,
},
],
})
export class AppModule {}
Required import HttpModule into your module
import { HttpModule } from '@nestjs/axios';
@Module({
providers: [],
controllers: [YourController],
imports: [
HttpModule,
],
exports: [],
})
export class YourModule {}
In your controller
import { HttpService } from '@nestjs/axios';
import { Controller, HttpStatus, Res, BadRequestException } from '@nestjs/common';
@Controller('your-controller')
export class YourController {
constructor(
private httpService: HttpService,
) {}
async fetchApi(@Res() res) {
const urlAPI = 'https://xxx.vn';
try {
const source = await this.httpService.get(urlAPI,
{
headers: { Authorization: 'Basic XXX-TOKEN' },
},
);
return res.status(HttpStatus.OK).json({ ...source });
} catch (error) {
throw new BadRequestException(error.response?.statusText);
}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.