下面我以簡單的兩臺node服務器來講明如何使用nginx進行前端跨域訪問。html
const app = express();
app.get('/web/users',(req, res)=>{
res.json([{name:"張三",age:12},{name:"李四",age:14}]);
res.end()
})
app.listen(process.env.PORT || 8083);
複製代碼
同域下的前端代碼只需調用前端
function getUsers() {
var xhr=new XMLHttpRequest();
xhr.open('GET', 'http://localhost:8083/web/users');
xhr.send(null);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}else {
alert(xhr.statusText);
}
}
}
複製代碼
這裏有一點須要關注的是,先後端代碼處在同一個域下,xhr.open() url路徑寫成下面這樣也是能夠的,它會默認請求到http://localhost:8083/web/usersnode
xhr.open('GET', '/web/users');
複製代碼
下面咱們將node1服務器中的web/users接口刪除:nginx
const app = express();
app.listen(process.env.PORT || 8083);
複製代碼
前端此時天然沒法訪問後臺的web/users了,將報一個404錯誤。web
下面增長一個node2服務器,在localhost:8085上啓動,同時咱們將原先在8083上刪除的web/users接口搬遷到8085上:ajax
const app = express();
app.get('/web/users',(req, res)=>{
res.json([{name:"張三",age:12},{name:"李四",age:14}]);
res.end()
})
app.listen(process.env.PORT || 8085);
複製代碼
因爲8085實現了這個接口,咱們嘗試在原先8083端口下的ajax調用它試試:express
xhr.open('GET', 'http://localhost:8085/web/users');
複製代碼
如咱們所料,瀏覽器阻止了這次行爲,並拋出一個跨域錯誤。 npm
難道就沒法訪問那個接口了嗎?其實服務器之間和服務器之間是能夠相互調用的,阻止跨域訪問只是在瀏覽器端作的限制而已。json
下面我經過兩種方式來實現如何訪問到8085上的web/users接口。後端
原理就是交由8083後端去訪問8085端口接口,訪問完成交給前端
8083node後端實現代碼:
npm install request --save // 須要安裝一個http request模塊
複製代碼
const app = express()
const request = require('request')
// 訪問此接口時經過request模塊去訪問8085 再返回給前端。
app.get('/web/users',(req, res)=>{
var url='http://localhost:8085'+req.url
console.log(url) // http://localhost:8085/web/users
req.pipe(request(url)).pipe(res);
})
複製代碼
就是經過script 的src,向服務器請求數據,且這不受同源策略限制;而後服務器將相應的數據放入指定的函數回調名中,返回給前端。說的有點繞,下面經過實例講解: 8083前端請求8085,這裏已經再也不是ajax請求了,而是直接加載8085上資源。
<script>
function getUsers(data) {
alert(data)
}
</script>
<script src="http://localhost:8085/jsonp?callback=getUsers"></script>
複製代碼
上述代碼第一個script標籤訂義了一個函數getUsers 可是並無執行,只是定義了而已,要想有執行能力,須要
getUsers(data)
複製代碼
因此咱們要讓第二個標籤script src="http://localhost:8085/jsonp?callback=getUsers" 返回getUsers(data)內容便可,這樣第一個標籤內定義的函數就能夠執行了。返回接口內容只須要放到函數參數裏便可
後臺8085實現:
const app = express();
const querystring=require('querystring')
const url=require('url')
// 處理前端jsonp請求
app.get('/jsonp',(req,res)=>{
var qs = querystring.parse(req.url.split('?')[1]); //{callback:'getUsers'}
var users=JSON.stringify([{name:"張三",age:12},{name:"李四",age:14}]) // 注意須要傳成字符串格式
var callback=`${qs.callback}(${users})`
res.end(callback)
})
複製代碼
前端返回
是否是有點黑魔法的味道!可是缺點也是明顯的,首先經過此方式有必定安全性的,經過callback後加一些亂七八糟的東西可能會有xss攻擊,最主要的是jsonp不支持post方法。
此方式即相似於第一種node代理方式,也是經過服務器和服務器之間通訊,只是不須要8083下後臺服務器本身去訪問8085,而是專門交給nginx,爲何?姑且認爲nginx更加專業吧! nginx配置
server {
listen 8007; # nginx啓動端口,須要訪問這個端口才可以代理
server_name localhost:8083; # 須要代理的服務器
location / { # 若是你訪問127.0.0.1/8002/的話nginx去請求
proxy_pass http://localhost:8083;
}
location /web { #訪問/web/aa時會映射成http://localhost:8085/web/aa;
proxy_pass http://localhost:8085;
}
}
複製代碼
8083請求路徑
xhr.open('GET', '/web/users');
複製代碼
CORS全稱是跨域資源共享 是一個W3C標準,它規定瀏覽器容許發送ajax到不一樣域下的服務器來獲取數據,從而克服了原來限制,使用CORS須要先後端都支持,現代瀏覽器基本上都支持。具體CORS的知識能夠參考阮一峯博客 www.ruanyifeng.com/blog/2016/0…
app.use('*',function (req, res, next) {
res.header('Access-Control-Allow-Origin', '*'); //這個表示任意域名均可以訪問,這樣寫不能攜帶cookie了。
//res.header('Access-Control-Allow-Origin', 'http://www.baidu.com'); //這樣寫,只有www.baidu.com 能夠訪問。
res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');
res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');//設置方法
if (req.method == 'OPTIONS') {
res.send(200);
}
else {
next();
}
});
複製代碼
或者使用現成的CORS模塊
npm install cors
複製代碼
var express = require('express')
var cors = require('cors')
var app = express()
var corsOptions = {
origin: 'http://www.baidu.com',
optionsSuccessStatus: 200
}
app.get('/products/:id', cors(corsOptions), function (req, res, next) {
res.json({msg: '只有百度能夠訪問'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})
複製代碼
若有不正確,請指正^_^