2017-09-09 54 views
3

我有一個的RESTify設置是這樣的:無法從反應/ Axios公司作出POST請求使用JSON來的RESTify服務器

var restify = require('restify'); 

const server = restify.createServer(); 

//server.use(restify.plugins.acceptParser(server.acceptable)); // [1] 
server.use(restify.plugins.queryParser()); 
server.use(restify.plugins.bodyParser()); 

server.use(function(req, res, next) { 
    console.log(req); // <-- Never see the POST from React here 
    res.setHeader('Access-Control-Allow-Origin', '*'); 
    res.setHeader('Access-Control-Allow-Headers', '*'); 
    res.setHeader('Access-Control-Allow-Methods', '*'); 
    next(); 
}); 

我定義了一堆GETPOST路線,到目前爲止,它的工作完美的罰款。我從Android應用程序,Python腳本調用服務器,並使用curl進行測試。沒有問題。整齊!

但是,現在我已經使用React實現了一個Web應用程序,並且想要使用axios包提出對restify API的請求。 GET請求是好的,所以我排除URL中的任何錯別字或這樣的事情。

但類似下面的POST請求將無法正常工作:

var data = {"test": "hello"}; 
axios.post("http://.../api/v1/message/question/public/add", data) 
    .then(function (response) { 
    console.log("Test question sent!"); 
    }) 
    .catch(function (error) { 
    console.log(error); 
    }); 

當我與瀏覽器開發者工具檢查,我可以看到瀏覽器試圖讓一個OPTIONS請求(不是POST)到該網址。從我讀過的內容來看,我認爲這是因爲瀏覽器正在進行「預發光請求」。問題是我得到一個405 Method Not Allowed錯誤:

Request URL: http://.../api/v1/message/question/public/add 
Request method: OPTIONS 
Remote address: ... 
Status code: 405 Method Not Allowed 

Response headers (178 B)  
    Server: restify 
    Allow: POST 
    Content-Type: application/json 
    Content-Length: 62 
    Date: Sat, 09 Sep 2017 08:16:32 GMT 
    Connection: keep-alive 
Request headers (485 B) 
    Host: ... 
    User-Agent: Mozilla/5.0 (X11; Ubuntu; Linu…) Gecko/20100101 Firefox/55.0 
    Accept: text/html,application/xhtml+xm…plication/xml;q=0.9,*/*;q=0.8 
    Accept-Language: en-ZA,en-GB;q=0.8,en-US;q=0.5,en;q=0.3 
    Accept-Encoding: gzip, deflate 
    Access-Control-Request-Method: POST 
    Access-Control-Request-Headers: content-type 
    Origin: http://... 
    DNT: 1 
    Connection: keep-alive 

但是爲什麼?我允許所有Access-Control-Allow-Methods重新定義。一切正常,除了POST請求,只有當他們來自瀏覽器(與React Web應用程序)。我想這是因爲OPTIONS請求,但我不知道如何處理它。

順便說一句JSON.stringify(data)POST請求通過,但API期望Json而不是字符串。而且,由於使用其他方法,它的工作原理非常好,我不想僅僅爲了解決這個問題而改變restify代碼。

[1]如果我用這條線,我得到以下錯誤:AssertionError [ERR_ASSERTION]: acceptable ([string]) is required at Object.acceptParser (/home/bob/node_modules/restify/lib/plugins/accept.js:30:12)

回答

1

如果您的服務器不允許默認OPTIONS,你可以添加一個明確的處理程序:

server.opts(/\.*/, function (req, res, next) { 
    res.send(200); 
    next(); 
}); 

另一個可能的問題是,你不會有效果預期以下標題:

res.setHeader('Access-Control-Allow-Headers', '*'); 
res.setHeader('Access-Control-Allow-Methods', '*'); 

*通配符值TH規範允許使用,但瀏覽器尚不支持它們。所以,你必須做的卻是,明確在這些值指定方法和標頭,允許:

res.setHeader('Access-Control-Allow-Headers', 'content-type'); 
res.setHeader('Access-Control-Allow-Methods', 'POST'); 

這是因爲對於CORS預檢OPTIONS請求所請求的頭部有這樣的:

Access-Control-Request-Method: POST 
Access-Control-Request-Headers: content-type 
Origin: http://... 

而且這些請求標頭指示的是,瀏覽器詢問服務器,以此原點運行的某些代碼想要向您的服務器發出POST請求,該請求會向請求添加特定的Content-Type。您是否願意收到POST請求,並添加他們自己的Content-Type

因此,在響應於該預檢OPTIONS請求,瀏覽器需要接收一個Access-Control-Allow-Methods響應標頭,其明確允許POST,與Access-Control-Allow-Headers響應標頭,其明確允許Content-Type沿。

+0

我找到了一個解決方案,請看我的答案。我實際上嘗試了顯式設置而不是通配符,但沒有任何工作。在Access-Control-Allow-Methods中是否有一個'OPTIONS'沒有任何區別。我很快嘗試了您的解決方案。 'OPTIONS'請求現在返回200,但沒有'POST'跟隨。再次,獨立如果我使用通配符或不。我想我仍然失去了興趣。 – Christian

+0

你的回答肯定是朝着正確的方向發展的,我發現你最後一句的解釋非常有用 - 這遠離我的背景。因此,我upvote。非常感激! – Christian

1

經過幾個小時後,我終於找到了一個solution。我已經改變了我restify服務器代碼如下:

var restify = require("restify"); 
var corsMiddleware = require('restify-cors-middleware') 

var cors = corsMiddleware({ 
    preflightMaxAge: 5, //Optional 
    origins: ['*'], 
    allowHeaders: ['API-Token'], 
    exposeHeaders: ['API-Token-Expiry'] 
}); 


// WITHOUT HTTPS 
const server = restify.createServer(); 

server.pre(cors.preflight); 
server.use(cors.actual); 
... 
(rest is the same as above) 

說實話,我沒有真正的想法是什麼做的實際。但它正在發揮作用,並且今天已經耗費了我太多的精力。我希望它能在某些時候幫助別人。一切似乎都是從restify相當新的變化。