2016-05-22 30 views
1

我試圖向REST API提出請求。這是一個CORS請求。 我的前端:角1.5(本地主機:3000) 我的後端:Django的(***** ddns.net)CORS與Django和Angular的預檢請求

所以我使用的服務(由人誰不希望共享的代碼所做:(),那就是在真正的請求(預檢)之前做一個OPTIONS請求。確切地說,這個調用是通過UI-路由器狀態定義的解析選項進行的。 Django有CORS允許*。

這個是我在谷歌鉻中得到的錯誤:

XMLHttpRequest cannot load https://****.net/api/myprofile. The request was redirected to 'https://*****.net/punchclock/api/myprofile/', which is disallowed for cross-origin requests that require preflight. 

如果我在控制器中做一個經典的$ http請求,它我工作。

這是請求收到我的Django:

+6655:5740d0f9:10| 
OPTIONS /punchclock/api//myprofile HTTP/1.0| 
Host:*****.net| 
Connection:close| 
Pragma:no-cache| 
Cache-Control:no-cache| 
Access-Control-Request-Method:GET| 
Origin:http%3a//localhost%3a3000| 
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36| 
Access-Control-Request-Headers:accept, authorization| 
Accept:*/*| 
Referer:http%3a//localhost%3a3000/dashboard| 
Accept-Encoding:gzip, deflate, sdch| 
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4,es;q=0.2 
-6655:5740d0f9:10 

這是我得到的迴應,如果我與郵差做到這一點(它正在與郵差當我做一個OPTIONS請求)

Access-Control-Allow-Headers →x-requested-with, content-type, accept, origin, authorization, x-csrftoken 
Access-Control-Allow-Methods →GET, POST, PUT, PATCH, DELETE, OPTIONS 
Access-Control-Allow-Origin →* 
Access-Control-Max-Age →86400 
Allow →GET, HEAD, OPTIONS 
Connection →keep-alive 
Content-Type →application/json 
Date →Sat, 21 May 2016 21:15:02 GMT 
Server →nginx/1.6.2 
Transfer-Encoding →chunked 
Vary →Accept 
X-Frame-Options →SAMEORIGIN 

我認爲這是Django方面的一個問題,我不知道。如果您有任何想法...(我需要學習很多關於CORS的...)

回答

0

這可能是因爲您發送的一些標頭是不允許的。爲了確保,只需進入google chrome調試器並複製請求標題並使用郵遞員發送它們。如果失敗消除標題,直到找出哪一個不被允許。

有一個similar answer here可能有所幫助。具體地說

根據W3 CORS Spec Section 6.2 Preflight Requests,如果提交的任何頭不匹配允許的頭,則預檢必須拒絕該請求。

+0

我做了你所說的。首先,我檢查了鉻調試器,這就是我得到的結果: '第一個請求,OPTIONS返回200 請求方法:選項 狀態碼:200 OK 遠程地址:**。***。* **。***:***' 但第二個: '請求URL:https://*****.ddns.net/api/myprofile 請求方法:GET 狀態碼:301永久移動 遠程地址:**。***。***。***:***' 另外我試圖使用郵遞員(+攔截器插件)添加所有標題,它也返回一個200。 – NOaMTL

+0

然後你的問題不是CORS,如果你從OPTIONS得到200,真正的請求301是我想的重定向,所以服務器端的人應該能夠幫助你。或者在重定向時向新網址發出第二個請求 –

+0

我試圖使用所有頭文件並模擬郵遞員獲取郵件,這是一個200 ...我很困惑。 而且我也嘗試直接對redirect url進行OPTIONS和GET,並且遇到同樣的問題。 – NOaMTL

2

Access-Control-Allow-Origin是CORS (Cross-Origin Resource Sharing) header

當網站A試圖從網站B獲取內容時,網站B可以發送訪問控制允許原始響應標頭,告訴瀏覽器該網頁的內容可以被某些來源訪問。 (源是域,加上方案和端口號。)默認情況下,站點B的頁面不能被任何其他來源訪問;使用Access-Control-Allow-Origin標題爲特定請求源的跨源訪問打開了一扇門。

對於每個資源/頁站點B要做出一個網站訪問,站點B應該成爲其頁面與響應頭:

Access-Control-Allow-Origin: http://siteA.com 

現代瀏覽器不會徹底阻止跨域請求。如果站點A從站點B請求一個頁面,瀏覽器將實際獲取網絡級別上請求的頁面,並檢查響應標題是否將站點A列爲允許的請求者域。如果站點B未指示站點A被允許訪問此頁面,瀏覽器將觸發XMLHttpRequest的錯誤事件,並拒絕對發出請求的JavaScript代碼的響應數據。

非簡單的要求:

在網絡層面會發生什麼事能比上述解釋稍微複雜一些。如果請求是「非簡單」請求,則瀏覽器首先發送無數據「預檢」OPTIONS請求,以驗證服務器是否接受請求。當(或兩者之一)請求是非簡單的:

使用non-simple request頭部使用除GET或POST(例如PUT,DELETE)之外的HTTP動詞;唯一簡單的請求標頭是:Accept Accept-Language Content-Language Content-Type(當它的值爲application/x-www-form-urlencoded,multipart/form-data或text/plain時,這只是簡單的)如果服務器使用與非簡單動詞和/或非簡單標題匹配的適當響應標題(用於非簡單標題的訪問控制 - 允許標題,用於非簡單動詞的訪問控制 - 允許 - 方法)響應OPTIONS預檢,那麼瀏覽器發送實際的請求。

假設站點A要發送的/ SomePage的PUT請求,與應用/ JSON的非簡單的內容類型值,瀏覽器將首先發送一個預檢要求:

OPTIONS /somePage HTTP/1.1 
Origin: http://siteA.com 
Access-Control-Request-Method: PUT 
Access-Control-Request-Headers: Content-Type 

注意瀏覽器自動添加Access-Control-Request-MethodAccess-Control-Request-Headers;你不需要添加它們。這OPTIONS預檢得到成功響應頭

Access-Control-Allow-Origin: http://siteA.com 
Access-Control-Allow-Methods: GET, POST, PUT 
Access-Control-Allow-Headers: Content-Type 

當發送實際的請求(預檢完成後),該行爲等同於一個簡單的請求是如何處理的。換句話說,其預檢成功的非簡單請求被視爲與簡單請求相同(即服務器必須仍然爲實際響應再次發送Access-Control-Allow-Origin)。

的瀏覽器發送實際的請求:

PUT /somePage HTTP/1.1 
Origin: http://siteA.com 
Content-Type: application/json 

{ "myRequestContent": "JSON is so great" } 

而且服務器返回一個Access-Control-Allow-Origin,只是因爲它會爲一個簡單的要求:

Access-Control-Allow-Origin: http://siteA.com 

約一點點的更多信息,請參見Understanding XMLHttpRequest over CORS非簡單的請求。

我相信這會幫助您更好地理解CORS問題和解決方案。