我可能遗漏了一些东西或者做错了什么。 我有一个NestJS应用程序,它正在尝试向外部API发出http请求。 我想能够拦截这个发送的请求并在执行之前修改其标头。
我尝试使用拦截器,但没有成功,入站的http请求被拦截了,但是出站的没有。 任何建议或帮助将不胜感激。
我可能遗漏了一些东西或者做错了什么。 我有一个NestJS应用程序,它正在尝试向外部API发出http请求。 我想能够拦截这个发送的请求并在执行之前修改其标头。
我尝试使用拦截器,但没有成功,入站的http请求被拦截了,但是出站的没有。 任何建议或帮助将不胜感激。
首先让我们处理一下:
我尝试使用拦截器,但并没有成功,入站http请求被拦截了,但出站请求却没有。
根据文档的说明,完全可以拦截响应。
@Injectable()
export class TransformHeadersInterceptor implements NestInterceptor {
intercept(
context: ExecutionContext,
call$: Observable<any>,
): Observable<any> {
// Get request headers, e.g.
const userAgent = context.switchToHttp().getRequest().headers['user-agent'];
// Not sure if headers are writeable like this, give it a try
context.switchToHttp().getResponse().headers['x-api-key'] = 'pretty secure';
return call$;
}
}
如果要根据响应数据操作标头。您可以像这样访问数据:
return call$.pipe(map(data => {
// Your code here
return data;
}));
我对以下内容有一些想法:
我有一个NestJS应用程序,试图向外部API发出http请求。我希望能够拦截这个即将发出的请求并在执行之前修改其中的标头。
因此,我认为有两种使用情况。首先,您有一组默认标头,最初分配给http客户端并与每个请求一起发送。例如:
import { HTTP_TOKEN } from './constants';
import * as http from 'request-promise-native';
export const httpProviders: any = [
{
provide: HTTP_TOKEN,
useFactory: () => {
return http.defaults({
headers: {
'Accept': 'application/json',
'Content-type': 'application/json',
'User-agent': 'my--app',
},
});
},
},
];
其次,您需要根据请求创建和分配标头。这是使用拦截器时的情况。在身份验证方面,您可以考虑使用守卫,就像tano在他的答案中建议的那样。
我曾经遇到过类似的问题,需要修改/添加响应头。以下代码对我有用:
@Injectable()
export class TransformHeadersInterceptor implements NestInterceptor {
intercept(
context: ExecutionContext,
call$: Observable<any>,
): Observable<any> {
return call$.pipe(
map((data) => {
// pipe call to add / modify header(s) after remote method
let req = context.switchToHttp().getRequest();
req.res.header('x-api-key', 'pretty secure');
return data;
}),
);
}
}
我可以举一个使用外部 API 调用的例子:
import { PaginateModel, PaginateResult, Document } from 'mongoose';
import { AxiosInstance } from 'axios';
import { UseGuards, InternalServerErrorException, Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { Context } from './decorators/ctx.decorator';
@Injectable()
@UseGuards(AuthGuard('jwt'))
export abstract class ServiceBase<T extends Document> {
protected abstract readonly path: string;
constructor(protected readonly externals: Object, protected readonly model: PaginateModel<T>) {}
async create(data: T, ctx: Context): Promise<T> {
try {
this.validate(data);
const { lng, core } = this.separate(data);
const catalog = new this.model(core);
const head = await catalog.save();
Object.assign(head, lng);
const Authorization = ctx.token;
const axios: AxiosInstance = this.externals[ctx.lang];
try {
const resp = await axios.post(`${this.path}`, head, { headers: { Authorization } });
return resp.data;
} catch (err) {
// in case of any error the head record should be removed.
catalog.remove();
throw err;
}
} catch (err) {
console.log(err);
throw new InternalServerErrorException(err);
}
}
abstract async validate(data: T): Promise<any>;
abstract separate(data: T);
async update(id: string, data: T, ctx: Context): Promise<T> {
try {
const curr = await this.model.findById(id).exec();
const { lng, core } = this.separate(data);
Object.assign(curr, core);
await curr.save();
Object.assign(core, lng);
const Authorization = ctx.token;
const axios: AxiosInstance = this.externals[ctx.lang];
const resp = await axios.put(`${this.path}/${id}`, core, { headers: { Authorization } });
return resp.data;
} catch (err) {
throw new InternalServerErrorException(err);
}
}
async get(id: string, ctx: Context): Promise<T> {
try {
const Authorization = ctx.token;
const axios: AxiosInstance = this.externals[ctx.lang];
const resp = await axios.get(`${this.path}/${id}`, { headers: { Authorization } });
return resp.data;
} catch (err) {
console.log(err);
return null;
}
}
async findOne(query: object): Promise<T> {
const data = await this.model.findOne(query, { _class: 0 }).exec();
return data;
}
async findAll(ctx: Context): Promise<T[]> {
try {
const Authorization = ctx.token;
const axios: AxiosInstance = this.externals[ctx.lang];
const resp = await axios.get(`${this.path}`, {
headers: { Authorization },
});
return resp.data;
} catch (err) {
console.log(err);
return null;
}
}
async find(query: {} = {}, page: number, rows: number, ctx: Context): Promise<PaginateResult<T>> {
try {
const Authorization = ctx.token;
const axios: AxiosInstance = this.externals[ctx.lang];
const resp = await axios.get(`${this.path}`, {
params: { page, rows },
headers: { Authorization },
});
return resp.data;
} catch (err) {
console.log(err);
return null;
}
}
}
其中 externals 是:
import axios, { AxiosInstance } from 'axios';
const config = require('../../config/settings.json');
export const externalProviders = {
provide: 'ExternalToken',
useFactory: () => {
const externals = {};
for (const lang in config.externals) {
externals[lang] = axios.create({
baseURL: config.externals[lang],
});
}
return externals;
}
};