Node 代理訪問(wèn)的實(shí)現(xiàn)
NODE代理訪問(wèn)
1. 場(chǎng)景
- 本地開(kāi)發(fā),代理訪問(wèn),防止跨域(一般通過(guò)webpack配置代理即可),特殊情況如攜帶一些自定義的登錄cookie則需要通過(guò)自己寫(xiě)node
- 作為一種server中間層,單線程異步可以緩解服務(wù)器壓力。長(zhǎng)鏈接websocket通常使用node搭建
2. 技術(shù)框架
- node - koa2 體量小,輕便易用。
- 路由koa-router koa配套路由,中間件支持async
- koa2-request 基于async對(duì) request的封裝,這里本人git上找的,可靠性帶考量,若基于生產(chǎn)環(huán)境建議使用request自行封裝
- koa-bodyparser 請(qǐng)求參數(shù)解析格式化-中間件
3. 上代碼
3.1 創(chuàng)建應(yīng)用 app.js
const Koa = require('koa') const bodyParser = require('koa-bodyparser') // 路由 const router = require('./router') const app = new Koa() app.use( bodyParser({ // 返回的對(duì)象是一個(gè)鍵值對(duì),當(dāng)extended為false的時(shí)候,鍵值對(duì)中的值就為'String'或'Array'形式,為true的時(shí)候,則可為任何數(shù)據(jù)類(lèi)型。 extended: true }) )
3.2 允許跨域 app.js
app.use(async (ctx, next) => { ctx.set('Access-Control-Allow-Origin', '*') ctx.set('Access-Control-Allow-Headers', 'content-type') ctx.set( 'Access-Control-Allow-Methods', 'OPTIONS,GET,HEAD,PUT,POST,DELETE,PATCH' ) await next() })
3.2 使用路由
// app.js app.use(router.routes()) // router.js const Router = require('koa-router') let koaRequest = require('./httpRequest') const router = new Router() router.get('/*', async (ctx, next) => { const url = setQuestUrl(ctx.url) try { let res = await koaRequest(url, 'GET', ctx) ctx.body = res } catch (err) { ctx.body = err } }) router.post('/*', async (ctx, next) => { const url = setQuestUrl(ctx.url) try { let res = await koaRequest(url, 'POST', ctx) ctx.body = res } catch (err) { ctx.body = err } }) function setQuestUrl(url) { if (/^\/t/.test(url)) { return 'host1'+ url.replace(/^\/t/, '') } if (/^\/xt/.test(url)) { return 'host2' + url.replace(/^\/xt/, '') } } module.exports = router
- router.get('/*', async (ctx, next) => {}) koa路由 ‘/*' 為通配符,匹配所有g(shù)et請(qǐng)求;next方法調(diào)用表示進(jìn)入下一個(gè)中間件;
- ctx請(qǐng)求上下文,ctx.request.body post請(qǐng)求參數(shù)
- koa的中間件原理 洋蔥圈模型:
const Koa = require('koa2'); const app = new Koa(); // logger app.use(async (ctx, next) => { console.log('第一層洋蔥 - 開(kāi)始') await next(); const rt = ctx.response.get('X-Response-Time'); console.log(`${ctx.method} ${ctx.url} - ${rt}`); console.log('第一層洋蔥 - 結(jié)束') }); // x-response-time app.use(async (ctx, next) => { console.log('第二層洋蔥 - 開(kāi)始') const start = Date.now(); await next(); const ms = Date.now() - start; ctx.set('X-Response-Time', `${ms}ms`); console.log('第二層洋蔥 - 結(jié)束') }); // response app.use(async ctx => { console.log('第三層洋蔥 - 開(kāi)始') ctx.body = 'Hello World'; console.log('第三層洋蔥 - 結(jié)束') }); app.listen(8000); // 輸出 第一層洋蔥 - 開(kāi)始 第二層洋蔥 - 開(kāi)始 第三層洋蔥 - 開(kāi)始 第三層洋蔥 - 結(jié)束 第二層洋蔥 - 結(jié)束 第一層洋蔥 - 結(jié)束
setQuestUrl 此方法主要是將前端訪問(wèn)的路徑,根據(jù)第一級(jí)轉(zhuǎn)發(fā)到不同的host上
例如: /t -> host1
3.3 轉(zhuǎn)發(fā)請(qǐng)求 httpRequest.js
本例主要為了代理訪問(wèn)并攜帶Cookie, const.js 為寫(xiě)死的要攜帶的cookie
let koa2Req = require('koa2-request') let constConfig = require('./const') let iToken = constConfig.iToken let koaRequest = async function(url, method, ctx) { let options = { method: method, uri: url, timeout: 120000, body: ctx ? { ...ctx.request.body } : null, headers: {}, json: true // Automatically stringifies the body to JSON } options.headers['Cookie'] = `i-token=${iToken}` //設(shè)置cookie let res = await koa2Req(options) return res.body } // node-mon async function getTestToken() { if (!constConfig.iToken) { let url = `http://xt.eqxiu.com/tui/app/radar/test/getToken?companyId=${constConfig.companyId}&staffId=${constConfig.staffId}` try { let res = await koaRequest(url, 'GET') iToken = res.obj console.log('token已拿到:' + iToken) } catch (e) { console.log(e) } } } getTestToken() module.exports = koaRequest
3.4 最后設(shè)置端口等
const app = require('./app') //const createWebsocket = require('./websocket') const server = require('http').createServer(app.callback()) server.setTimeout(2 * 60 * 1000) //設(shè)置超時(shí)時(shí)間 const { PORT = 3000 } = process.env server.listen(PORT, () => { console.log(`Listening on port ${PORT}`) })
3.5 本地開(kāi)發(fā),熱重啟
安裝 nodemon
yarn add nodemon
設(shè)置忽略監(jiān)聽(tīng)
nodemon.josn node項(xiàng)目根目錄下
{ "ignore": ["node_modules/*"] //忽略node_modules下文件修改的監(jiān)聽(tīng) }
package.josn
通過(guò)npm run server啟動(dòng)
{ "dependencies": { "koa": "^2.8.1", "koa-bodyparser": "^4.2.1", "koa-router": "^7.4.0", "koa2-request": "^1.0.4", "nodemon": "^1.19.1" }, "scripts": { "server": "nodemon index.js" } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Node.js的文件權(quán)限及讀寫(xiě)flag詳解
Node.js對(duì)文件的讀寫(xiě)還是相當(dāng)靈活的,因?yàn)樽约豪鲜怯洸蛔∥募蚰夸洐?quán)限的數(shù)值表達(dá)和字符表達(dá)。所以整理出這篇文章,方便以后查閱,下面來(lái)一起看看吧。2016-10-10詳解nodejs通過(guò)響應(yīng)回寫(xiě)的方式渲染頁(yè)面資源
本篇文章主要介紹了詳解nodejs通過(guò)響應(yīng)回寫(xiě)的方式渲染頁(yè)面資源,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-04-04node.js解決客戶(hù)端請(qǐng)求數(shù)據(jù)里面中文亂碼的事件方法
本文主要介紹了node.js解決客戶(hù)端請(qǐng)求數(shù)據(jù)里面中文亂碼的事件方法,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12運(yùn)行Node.js的IIS擴(kuò)展iisnode安裝配置筆記
這篇文章主要介紹了運(yùn)行Node.js的IIS擴(kuò)展iisnode安裝配置筆記,iisnode的擴(kuò)展可以把Node.js程序托管到IIS,托管之后也意味著可以使用IIS里面的各種功能,需要的朋友可以參考下2015-03-03