在上一節(jié)索赏,我們介紹了如何進行生產(chǎn)環(huán)境打包。一般情況下將打好的生產(chǎn)包和后臺程序部署到tomcat染簇,然后啟動tomcat即可通過域名端口號訪問参滴。那么如果是這種情況,生產(chǎn)包與后臺程序不存在跨域問題锻弓;如果生產(chǎn)包與后臺程序違背了同源策略
[1]砾赔,那么就會發(fā)生跨域問題。還有一種情況必然會發(fā)生跨域問題:開發(fā)環(huán)境中與后臺程序進行測試青灼。
跨域限制是服務(wù)端的一個行為暴心,當
后端程序開啟對某些域名的訪問限制后
,只有同域名或者制定域名下的頁面可以調(diào)用杂拨,這樣相對來說更安全专普、圖片也可以防盜鏈〉粒跨域限制一般只在瀏覽器端存在檀夹,對于服務(wù)端或iOS、Android等客戶端是不存在的策橘。
我們注意到后端程序其實是可以處理跨域問題炸渡,使用的方法是CORS
(稍微會后詳細文章介紹CORS)。那么如果只通過前端代碼或者配置前端的運行環(huán)境如何解決跨域問題丽已?
- JSONP
- 使用代理
JSONP是使用了<script></script>標簽的特性:可以加載非同源策略的特性實現(xiàn)回調(diào)函數(shù)處理返回數(shù)據(jù)蚌堵。由于我們開發(fā)的是SPA應(yīng)用,在組件內(nèi)無法直接使用<script>標簽沛婴;另外如果在index.html文件里使用<script>標簽倒是可以吼畏,但是一個項目有很多的請求,那每遇到請求就新增一個<script>標簽顯然是不可取的嘁灯。
所以本篇著重介紹使用代理解決跨域-----使用基于Node.js的request
庫做代理泻蚊。
1. 安裝request
npm install request --save-dev
在根目錄下新建proxy.js,寫入以下內(nèi)容:
const request = require('request');
const http = require('http');
// 知乎url
const BaseUrl = 'http://news-at.zhihu.com/api/4';
// 設(shè)置代理的域名和端口
const hostname = '127.0.0.1';
const port = '8080';
const imgPort = "8081";
// 創(chuàng)建API代理
const apiServer = http.createServer((req, res) => {
const url = BaseUrl + req.url;
const options = {
url: url
};
function callback(error, response, body) {
if(!error && response.statusCode === 200) {
// 設(shè)置編碼類型丑婿,否則中文會亂碼
res.setHeader('Content-type', 'text/plain;charset=UTF-8');
// 設(shè)置跨域
res.setHeader('Access-Control-Allow-Origin', '*');
// 返回結(jié)果
res.end(body);
}
}
request.get(options, callback);
})
// 監(jiān)聽apiServer
apiServer.listen(port, hostname, () => {
console.log(`接口代理運行在http://${hostname}:${port}`);
})
// 創(chuàng)建imgServer
const imgServer = http.createServer((req, res) => {
console.log(req.url)
const url = req.url.split('/img/')[1];
const options = {
url: url,
encoding: null
}
function callback(error, response, body) {
if(!error && response.statusCode === 200) {
const contentType = response.headers['content-type'];
res.setHeader('Content-type', contentType);
res.setHeader('Access-Control-Allow-Origin', '*');
res.end(body);
}
}
request.get(options, callback);
})
// 監(jiān)聽imgServer
imgServer.listen(imgPort, hostname, () => {
console.log(`圖片代理運行在http:${hostname}:${imgPort}`);
})
上述代碼實現(xiàn)監(jiān)聽兩個端口:8080和8081藕夫。8080用于接口代理孽糖,8081實現(xiàn)圖片代理。比如請求http://news-at.zhihu.com/api/4/news/before/20180627毅贮,開發(fā)時改寫為http://127.0.0.1:8080/news/before/20180627办悟,圖片的真實地址是https://pic2.zhimg.com/v2-66bd54ab382ac860cec3822b3f8d7811.jpg開發(fā)時改寫成http://127.0.0.1:8081/img/v2-66bd54ab382ac860cec3822b3f8d7811.jpg。
運行以下命令:
node proxy.js
如果運行成功滩褥,會顯示兩條運行日志:
對于接口的Ajax請求病蛉,前端有很多實現(xiàn)方案,比如jQuery的$.ajax()方法瑰煎,但是為了使用Ajax這一個功能铺然,引入整個jQuery是不可取的。Vue官方提供vue-resource插件酒甸,但是不再維護魄健,而是推薦使用axios。
axios不僅在開發(fā)環(huán)境會用到插勤,在生產(chǎn)打包后也會用沽瘦,所以進行全局安裝:
npm install axios --save
在components文件夾內(nèi)新建axios.vue,代碼如下:
<template>
<div class="zhihu-list">
<ul class="stories">
<li
class="list"
v-for="(story, idx) in stories"
:key="idx"
>
<span>title: {{story.title}}</span>
<span>id: {{story.id}}</span>
<span>ga_prefix: {{story.ga_prefix}}</span>
<img
v-for="(img,imIdx) in story.images"
:key="imIdx"
:src="imgPath + img"
>
</li>
</ul>
</div>
</template>
<script>
import Util from '../Util.js';
export default {
name: '',
data() {
return {
stories: [],
imgPath: Util.imgPath
};
},
mounted() {
Util.ajax.get('/news/before/20180627').then(res => {
this.stories = res.stories;
})
}
}
</script>
<style scoped>
</style>
在app.vue中引入該組件(同title.vue农尖、count.vue引入方式一樣)析恋,打開瀏覽器效果如下:
注意:代理圖片可能會由于網(wǎng)絡(luò)原因?qū)е录虞d時間過長。
至此盛卡,我們實現(xiàn)了如何使用Node.js的request進行代理以解決跨域問題的問題助隧。
完整代碼github地址:https://github.com/zhiyuanMain/zhihu-daily
-
域名、協(xié)議滑沧、端口號至少一個不同即違背同源策略并村,那么在ajax訪問的時候就會出現(xiàn)跨域問題。 ?