web專案的編寫過程當中,常常會出現前後端進度不一致的情況,就像談戀愛的兩個人如果步調不一致,那麼肯定會很累,更有甚者因節奏的不一樣導致分手的下場,所以為了避免前後端走到“分手”的這一步,我們需要把前後端解耦開來,可是對於前端來說,你讓我自己寫假資料行啊,可是模擬不到網路請求這一步,那這個mock的假資料真是“食之無味,棄之可惜”,於是,
Node: "對面的女孩看過來,看過來,看過來~這裡的哥哥有點帥"
node挺身而出,幫我們用三兩句話就搭建起了一個代理伺服器,於是乎,前端:“麵包(資料)我有了,陽光(網路請求)我有了,你(後端)最後來給我愛情就好~”,啊,說了一堆廢話,還是來看看我們的可切換源資料的代理node伺服器是長啥樣吧~~
/**
* @author luojun <https://github.com/Luooojunnn>
* @desc 本中間伺服器可以切換資料來源,如需二次改造,請github上提問
*/
const http = require('http')
const url = require('url')
const path = require('path')
const fs = require('fs')
const colors = require('colors')
/**
* 環境判斷
*/
const ENV = process.argv[2] && process.argv[2].split('=')[1]
http.createServer((req, res) => {
try {
/**
* 將讀取api檔案寫在服務程式內,實現動態更新
* 遇到一個坑,就是node跑在gw根目錄導致這裡讀取檔案採用相對路徑就會讀不到東西
*/
let apiFile = JSON.parse(fs.readFileSync(`${path.join(__dirname, '../../data/apiManage.json')}`))
if (url.parse(req.url).pathname !== '/favicon.ico') {
// 判斷請求方式,請求引數
let reqMethod = req.method === 'GET' ? 'GET' : (req.method === 'POST' ? 'POST' : req.method)
// 定址回值
if (apiFile[url.parse(req.url, true).pathname.substring(1)]) {
res.setHeader('Access-Control-Allow-Origin', '*')
res.setHeader('Allow', '*')
res.setHeader('Access-Control-Allow-Headers', '*')
if (reqMethod === 'OPTIONS') {
res.end('')
}
// 根據環境變數選擇介面
let apiAdress = apiFile[url.parse(req.url, true).pathname.substring(1)][ENV]
// TODO 根據環境判斷是夠需要一個代理轉發
if (ENV === 'dev') {
console.log('在dev環境'.red)
// 儲存請求引數,用於轉發
let paramsData = ''
if (reqMethod === 'GET') {
paramsData = url.parse(req.url, true).search
} else if (reqMethod === 'POST') {
let res = ''
req.on('data', (reqData) => {
res += reqData
})
req.on('end', (reqData) => {
paramsData = res
console.log(paramsData)
})
}
console.log(`介面名 ${url.parse(req.url, true).pathname},採用 ${reqMethod} 請求方式,傳遞的引數是 ${paramsData}`)
let finalAddress = path.join(__dirname, '../../data/', apiAdress)
// dev環境 - 讀取介面,輸出json
let apiData = fs.readFileSync(finalAddress)
res.end(apiData.toString('utf8'))
} else {
console.log('在測試環境'.red)
// online環境 - 代理轉發 PS: hostname 不含協議
let hn = url.parse(apiAdress).hostname
let pt = url.parse(apiAdress).path
req.headers.host = hn //url.parse(apiAdress).host
let sRes = res
if (reqMethod === 'GET') {
if (url.parse(req.url, true).search) {
pt = '' + pt + url.parse(req.url, true).search
}
console.log(`介面名 ${url.parse(req.url, true).pathname},採用 ${reqMethod} 請求方式,傳遞的引數是 ${url.parse(req.url, true).search}`)
HCLIENTFC({
hostname: hn + '',
path: pt + '',
method: reqMethod + '',
headers: req.headers
}, (data, statusCode, header) => {
sRes.writeHead(Number(statusCode), header)
sRes.end(data)
}, '')
} else if (reqMethod === 'POST') {
let res = ''
req.on('data', (reqData) => {
res += reqData
})
req.on('end', (reqData) => {
console.log(`介面名 ${url.parse(req.url, true).pathname},採用 ${reqMethod} 請求方式,傳遞的引數是 ${res}`)
/**
* 將 host 頭部資訊改成online的域名資訊,否則host會指向程式碼裡的請求的localhost:9000
* !!! 為什麼一定要用 header ,因為可以在做爬蟲的時候,冒充瀏覽器端,越過有些程式碼的機器人識別
* */
HCLIENTFC({
hostname: hn + '',
path: pt + '',
method: reqMethod + '',
headers: req.headers
}, (data, statusCode, header) => {
sRes.writeHead(Number(statusCode), header)
sRes.end(data)
}, res)
})
}
}
} else {
res.writeHead(404)
res.end('')
}
}
} catch (e) {
res.end('介面解析出現了一些錯誤...')
throw new Error(e)
}
}).listen(9000, 'localhost', () => {
console.log('介面服務啟動在localhost:9000')
})
/**
* online伺服器
* @param {Object} obj - 需要參入的配置引數
* @param {string} obj.hostname - 目標地址ip或域名
* @param {string} obj.path - 請求路徑 (這裡忘寫導致出問題)
* @param {string} obj.method - 請求方法
* @param {Object} obj.headers - 請求頭
* @param {function} callback - 回撥
* @param {string} params - 轉發引數
*/
function HCLIENTFC ({ hostname, path = '/', method = 'GET', headers }, callback = () => { }, v = '') {
let resData = ''
console.log('介面的資訊引數:========1'.blue)
console.log('hostname:' + hostname)
console.log('path:' + path)
console.log('method:' + method)
console.log(headers)
console.log('post傳送的資料v:' + v)
console.log('介面的資訊引數:--------2'.blue)
/**
* 由於傳送了header,其accept接受的資料型別可能和返回的資料型別不一致,所以可能導致介面超時,必要時,可去掉髮送header
*/
const HCLIENT = http.request({
hostname,
path,
method,
headers
}, (res) => {
res.setEncoding('utf8')
res.on('data', (chunk) => {
resData += chunk
})
res.on('end', () => {
console.log('介面返回結果是:', resData.toString())
console.log('測試環境返回狀態碼:', res.statusCode)
console.log('測試環境返回響應頭:', res.headers)
callback(resData, res.statusCode, res.headers)
})
})
HCLIENT.on('error', (e) => {
console.log('出現錯誤,錯誤資訊為:' + e)
return resData
})
HCLIENT.write(v)
HCLIENT.end()
}
複製程式碼
node:"陽光大熊貨前來報到!!"
有啥不清楚的可以留言大家一起討論,共同學習進步!!sir!
git地址:一些好玩的Node
PS: 之前關於get、post請求引數的獲取判斷有誤,線已改正(180927)