2012-06-12 91 views
72

我在node.js的快速框架上編寫了一個REST API,它適用於Chrome中js控制檯的請求和URL欄等。現在試圖讓它適用於來自另一個應用程序,不同域(CORS)的請求。允許CORS REST請求到Heroku上的Express/Node.js應用程序

由javascript前端自動創建的第一個請求是/ api/search?uri =,並且在「預檢」OPTIONS請求中顯示爲失敗。

在我明確的應用程序,我加入CORS標頭,使用:

var allowCrossDomain = function(req, res, next) { 
    res.header('Access-Control-Allow-Origin', '*'); 
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS'); 
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With'); 

    // intercept OPTIONS method 
    if ('OPTIONS' == req.method) { 
     res.send(200); 
    } 
    else { 
     next(); 
    } 
}; 

和:

app.configure(function() { 
    app.use(express.bodyParser()); 
    app.use(express.methodOverride()); 
    app.use(app.router); 
    app.use(allowCrossDomain); 
    app.use(express.static(path.join(application_root, "public"))); 
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); 
}); 

從Chrome的控制檯我得到這些標題:

請求URL:http ://furious-night-5419.herokuapp.com/api/search?uri = http%3A%2F%2Focalocal%3A5000%2Fcollections%2F1%2Fdocuments%2F1

請求方法:OPTIONS

狀態代碼:200 OK

請求頭

Accept:*/* 
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3 
Accept-Encoding:gzip,deflate,sdch 
Accept-Language:en-US,en;q=0.8 
Access-Control-Request-Headers:origin, x-annotator-auth-token, accept 
Access-Control-Request-Method:GET 
Connection:keep-alive 
Host:furious-night-5419.herokuapp.com 
Origin:http://localhost:5000 
Referer:http://localhost:5000/collections/1/documents/1 
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.56 Safari/536.5 

查詢字符串參數

uri:http://localhost:5000/collections/1/documents/1 

響應頭

Allow:GET 
Connection:keep-alive 
Content-Length:3 
Content-Type:text/html; charset=utf-8 
X-Powered-By:Express 

這看起來像是缺少API應用程序發送的正確頭文件嗎?

謝謝。

+0

我在代碼中沒有寫到這個錯誤,但我不明白'OPTIONS'方法需要處理程序。有人能幫助我理解爲什麼不處理'POST'方法而不是處理'POST' **和**'OPTIONS'方法? –

回答

49

我已經在一個乾淨的ExpressJS應用上檢查了你的代碼,它工作得很好。

嘗試將您的app.use(allowCrossDomain)移動到配置功能的頂部。

+8

它做的原因是因爲你需要在'app.use(app.router)之前定義它;'乾杯! – Michal

+0

在我的情況下,當req.method =='OPTIONS'發回res.send(200)後,下一次POST不會被調用。我錯過了其他什麼? – Aldo

+0

2Aldo:需要代碼。可能你忘了一些標題?如果您的客戶端在您的服務器正確提供預檢OPTIONS請求後未發送POST,請嘗試檢查開發者工具控制檯。 WebKit將這類錯誤記錄到Web檢查器的控制檯。 – Olegas

1

爲withCredentials你需要這條線 xhr.withCredentials = true;

mdn docs xhr.withCredentials

在Express服務器之前,所有其他

`app.all('*', function(req, res, next) { 
    var origin = req.get('origin'); 
    res.header('Access-Control-Allow-Origin', origin); 
    res.header("Access-Control-Allow-Headers", "X-Requested-With"); 
    res.header('Access-Control-Allow-Headers', 'Content-Type'); 
    next(); 
});` 
0

這不可能是對大多數人的情況下添加此塊支持餅乾瀏覽這個問題,但我有這個完全相同的問題,解決方案與CORS無關。

原來,JSON Web Token的祕密string沒有在環境變量中定義,所以令牌無法被簽名。 這導致任何POST請求依賴於檢查或簽署令牌來獲取超時並返回503錯誤,告訴瀏覽器在CORS中存在錯誤,而不是。 在Heroku中添加環境變量解決了問題。

我希望這可以幫助別人。

+0

是的,這是我的問題。你能更具體地說明你是如何解決問題的。我仍然在開發中,正在運行Express.js w/node cors軟件包。 – alan

+0

@alan我在使用promise來驗證我的應用程序中的令牌,一些如何未定義JWT祕密,承諾永遠不會解決,這是[code](https://github.com/elbuki/remindr-api /blob/develop/src/middlewares/verifyToken.js)我在使用,如果你需要進一步的參考。 – CatBrownie

+0

感謝您的回覆。我會查看代碼。通過祕密我假設你正在談論第二個私鑰。我正在使用oauth2。 – alan

相關問題