全棧07 Express轉發前端請求實現跨域
阿新 • • 發佈:2018-11-10
http模組和https模組
使用了express的http模組實現了對前端http請求的簡單轉發,從而實現了跨域請求
const express = require('express'); const http = require('http'); const router = express.Router(); router.route('/') .get((req, res) => { const { url } = req.query; const proxyReq = http.request(url, remoteRes => remoteRes.pipe(res)); proxyReq.end(); }); module.exports = router; router.use('/proxy', proxy);
使用的時候:
export const QUERY_URL = 'https://wallstreetcn.com/live/global';
const X_URL = `/api/proxy?url=${encodeURIComponent(QUERY_URL)}`;
fetch(X_URL).then(v => console.log(v.text()))
但是這樣有一個問題,如果請求的資源型別為頁面資源(文字),如果是經過gzip壓縮的,直接處理會返回亂碼,需要使用zlib.createGunzip()
方法進行解壓縮處理後再進行轉發就可以了
const express = require('express'); const http = require('http'); const zlib = require('zlib'); const router = express.Router(); router.route('/') .get((req, res) => { const { url } = req.query; const proxyReq = request(url, (remoteRes) => { if (remoteRes.headers['content-encoding'] === 'gzip') { const gzip = zlib.createGunzip(); return remoteRes.pipe(gzip).pipe(res); } return remoteRes.pipe(res); }); proxyReq.end(); }); module.exports = router; router.use('/proxy', proxy);
request模組
但是還有一個問題,這樣的轉發只支援http請求的轉發,而不支援https的轉發,如果要修改就需要根據傳遞進來的url來確定使用http模組還是https模組
其實有更簡單的方式,那就是使用request模組
它支援http和https請求,簡單的使用可以參考這篇文章。
實現轉發的的時候,也使用pipe來進行轉發:
var request = require('request'); app.use('/api', function(req, res) { var url = apiUrl + req.url; req.pipe(request(url)).pipe(res); });
上面完整的請求傳遞給API,並且將相應傳遞給請求的發起者,支援GET/PUT/DELETE的其他請求方式
回到我們的例子中,使用request模組使程式碼大大簡化
const express = require('express');
const request = require('request');
const router = express.Router();
router.route('/')
.get((req, res) => {
const { url } = req.query;
req.pipe(request(url)).pipe(res);
});
module.exports = router;
router.use('/proxy', proxy);
request也不需要對gzip進行解壓,資料直接可用。
也可以對headers進行設定:
router.route('/')
.get((req, res) => {
const { url } = req.query;
const options = {
url,
headers: {
accept: req.headers.accept,
},
};
req.pipe(request(options)).pipe(res);
});
module.exports = router;