先後端分離來講,跨域請求是咱們第一個須要解決的問題。下面是我在開發中總結出來的一些經驗。
javascript
開發中,不少時候會出現Options請求(CORS預檢請求),可是有的時候又不會出現。某些請求不會觸發 CORS 預檢請求,這樣的請求被稱爲簡單請求,其餘的請求被稱爲非簡單請求。首先咱們來區分簡單請求和非簡單請求。css
瀏覽器將CORS請求分紅兩類:簡單請求(simple request)和非簡單請求(not-so-simple request)。
只要同時知足如下兩大條件,就屬於簡單請求。html
HEAD、GET、POST前端
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限於三個值application/x-www-form-urlencoded、multipart/form-data、text/plain凡是不一樣時知足上面兩個條件,就屬於非簡單請求
。瀏覽器對這兩種請求的處理,是不同的。java
如今咱們知道咱們哪些請求是簡單請求哪些是非簡單請求,上面有提到HTTP頭部和CORS跨域請求,CORS全稱Cross-origin resource sharing,也就是跨域資源共享,瀏覽器出於安全角度考慮限制跨域HTTP請求,這就是同源策略,因此後端須要設置請求頭部才能容許跨域。node
是逗號分隔的一個字符串,代表服務器容許的跨域請求的方法。jquery
是一個逗號分隔的字符串,代表服務器支持的全部頭信息字段,不限於瀏覽器在」預檢」中請求的字段。ajax
該字段表示是否能夠將對請求的響應暴露給頁面,通常來講是cookie。Credentials必須在先後端都被配置才能使帶credentials的CORS請求成功。jQuery能夠經過設置xhrFields: {withCredentials:true}
,promise能夠經過設置credentials: 'include'
。json
用來指定本次預檢請求的有效期,單位爲秒。segmentfault
表示資源是否被容許與給定的origin共享。
響應首部 Access-Control-Expose-Headers 列出了哪些首部能夠做爲響應的一部分暴露給外部。默認狀況下,只有六種 simple response headers (簡單響應首部)能夠暴露給外部:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。若是想要讓客戶端能夠訪問到其餘的首部信息,能夠將它們在 Access-Control-Expose-Headers 裏面列出來。
請求首部 Access-Control-Request-Headers 出現於 preflight request (預檢請求)中,用於通知服務器在真正的請求中會採用哪些請求首部。
請求首部 Access-Control-Request-Method 出現於 preflight request (預檢請求)中,用於通知服務器在真正的請求中會採用哪一種 HTTP 方法。由於預檢請求所使用的方法老是 OPTIONS ,與實際請求所使用的方法不同,因此這個首部是必要的。
若是須要發送cookie,先後端都被配置,前端須要設置jQuery能夠經過設置xhrFields: {withCredentials:true}
,promise能夠經過設置credentials: 'include'
。
服務器端須要設置res.setHeader('Access-Control-Allow-Credentials', 'true');
不然瀏覽器就會報錯:
須要注意的是,若是要發送Cookie,Access-Control-Allow-Origin就不能設爲星號,必須指定明確的、與請求網頁一致的域名。
同時,Cookie依然遵循同源政策,只有用服務器域名設置的Cookie纔會上傳,其餘域名的Cookie並不會上傳,且(跨源)原網頁代碼中的document.cookie也沒法讀取服務器域名下的Cookie。
這時候瀏覽器會報錯
//解析cookie的函數
function parseCookies (request) {
let list = {},
rc = request.headers.cookie;
rc && rc.split(';').forEach(function( cookie ) {
let parts = cookie.split('=');
list[parts.shift().trim()] = decodeURI(parts.join('='));
});
return list;
}
http.createServer(function (request, response) {
//讀取cookie
var cookies = parseCookies(request);
//寫入cookie
response.writeHead(200, {
'Set-Cookie': 'mycookie=test',
'Content-Type': 'text/plain'
});
response.end('Hello World\n');}).listen(8124);
})
複製代碼
對接後端的接口的時候,Content-Type的值是決定後端那邊怎麼去解析咱們的傳參的。Content-type經常使用幾個值:
1.text/html
2.text/plain
3.text/css
4.text/javascript
5.application/x-www-form-urlencoded
6.multipart/form-data
7.application/json
8.application/xml
前面幾個都很好理解,都是html,css,javascript的文件類型,後面四個是POST的發包方式。
html中表單提交的默認格式,jquery ajax請求默認的content-type默認也是這種格式,而且jquery會把data:{foo1:」bar1」,foo2:」bar2」}數據轉換成key1=value1&key2=value2,能夠經過processData來關閉是否提早處理數據,數據格式是key1=value1&key2=value2形式。
下面是jquery作data預處理的代碼,默認processData爲true,因此若是data有值就會進入判斷就會把json格式轉化爲key1=value1&key2=value2的格式
if ( s.data && ( s.processData || typeof s.data === "string" ) ) {
cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data;
// #9682: remove data so that it's not used in an eventual retry
delete s.data;
}複製代碼
multipart/form-data用在發送文件的POST包。
這裏Content-Type告訴咱們,發包是以multipart/form-data格式來傳輸,另外,還有boundary用於分割數據。
當文件太長,HTTP沒法在一個包以內發送完畢,就須要分割數據,分割成一個一個chunk發送給服務端,
那麼—用於區分數據快,然後面的數據sqe6Nhq4gtMfHLOY 就是標示區分包做用。
------WebKitFormBoundarysqe6Nhq4gtMfHLOY
Content-Disposition: form-data; name:"UserWxCode"
123
------WebKitFormBoundarysqe6Nhq4gtMfHLOY
Content-Disposition: form-data; name="CodeType"
Public
------WebKitFormBoundarysqe6Nhq4gtMfHLOY--複製代碼
發送請求的時候須要JSON.stringify一下,HTTP通訊中並不存在所謂的json,而是將string轉成json罷了,也就是,application/json能夠將它理解爲text/plain,普通字符串。
text/xml忽略xml文件頭中的關於編碼的設定(<?xml version=」1.0」 encoding=」UTF-8」?>
),默認採用us-ascii編碼。 application/xml會依照xml文件頭中編碼的設定。推薦使用application/xml
//fetch設置Headers,cookies
//方式1
let myHeaders = new Headers({
'Content-Type': 'application/json; charset=UTF-8',
'token': 123
});
//方式2
headers: {
'Content-Type': 'application/json; charset=UTF-8',
'token': 123
}
//發送cookies:
credentials: 'include'
//jquery ajax設置Headers,cookies
//設置header方式一
headers: {
UserName: 'zxplus',
EncryptKey: '1111'
},
//方式二
beforeSend: function(request) {
request.setRequestHeader("UserName", "zxplus");
},
//發送cookie
xhrFields: {
withCredentials:true //支持附帶詳細信息
},複製代碼
https://stackoverflow.com/questions/3393854/get-and-set-a-single-cookie-with-node-js-http-serverhttp://www.ruanyifeng.com/blog/2016/04/cors.htmlhttps://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORShttps://segmentfault.com/a/1190000006039533http://www.cnblogs.com/caoshiqing/p/6825608.htmlhttp://homeway.me/2015/07/19/understand-http-about-content-type/