Nestjs的Http模块
Nestjs的HttpModule模块打包了Axios并且暴露出HttpService接口,HttpService将Axios数据转换为Obervable并返回。比如,HttpService的Post方法在Nestjs源码中是这样写的。
post<T = any>(url: string,data?: any,config?: AxiosRequestConfig,): Observable<AxiosResponse<T>> {return defer(() => this.instance.post(url, data, config));}
默认情况下,HttpService发送的是JSON风格的请求,但是我们难免要和一些x-www-form-urlencoded风格的API打交道(我是在使用墨迹天气的API时遇到这个坑的)。因为Nestjs仅仅是对Axios进行了封装,因此要到Axios中找答案。
Axios官方说明
在Axois官方文档中对使用x-www-form-urlencoded format风格针对浏览器和node环境分别做了如下说明。
浏览器环境
在浏览器中,可以使用URLSearchParamsAPI接口。需要注意的是并不是所有浏览器都支持URLSearchParams,所以可能需要polyfill一下。
const params = new URLSearchParams();params.append('param1', 'value1');params.append('param2', 'value2');axios.post('/foo', params);
在浏览器中也可以使用qs库
const qs = require('qs');axios.post('/foo', qs.stringify({ 'bar': 123 }));
或者使用ES6风格的qs.
//这是官方文档的写法,但是我在nestjs中用import会报找不到模块的错误,需要改成//import * as qs from 'qs'//不确定浏览器中是否可以正常使用import qs from 'qs';const data = { 'bar': 123 };const options = {method: 'POST',headers: { 'content-type': 'application/x-www-form-urlencoded' },data: qs.stringify(data),url,};axios(options);
nodejs环境
在nodejs中,可以使用querystring或者qs模块,但是早期版本的querystring存在一些问题,因此官方推荐使用qs模块。//官方文档,未做验证const querystring = require('querystring');axios.post('http://something.com/', querystring.stringify({ foo: 'bar' }));
NestJs中的使用
按照Axios官方文档的推荐,使用qs库,由于qs在axios中封装,而Nestjs封装了Axois,因此不需要额外安装Axios或者qs就能直接使用。以墨迹天气的API接口为例,token和APPCODE需要换成相应内容即可正常使用。
import { Injectable, HttpService, Header } from '@nestjs/common';import { map } from 'rxjs/operators';import * as qs from 'qs';@Injectable()export class WeatherService {constructor(private httpService: HttpService) {}getWeatherId(id) {const data = { cityId: id,token:**************** };return this.httpService.post('http://aliv18.data.moji.com/whapi/json/alicityweather/forecast15days',qs.stringify(data),{headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',Authorization: 'APPCODE *******************',},},).pipe(map(response => response.data));// return this.httpService(options).pipe(// map(response=>response.data)// );}
