无法使用来自react / axios的JSON发出POST请求来解析服务器

时间:2017-09-09 08:29:55

标签: json reactjs cors axios 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个请求没问题,因此我会在网址或类似内容中排除任何拼写错误。

但是像下面这样的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)。我认为,从我读过的内容来看,这是因为浏览器正在制作一个&#34;预先发出的请求&#34;。问题是我收到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而不是字符串。而且由于所有其他方式它完全正常,我不想改变整理代码只是为了适应这个问题。

[1]如果我使用此行,则会收到以下错误:AssertionError [ERR_ASSERTION]: acceptable ([string]) is required at Object.acceptParser (/home/bob/node_modules/restify/lib/plugins/accept.js:30:12)

2 个答案:

答案 0 :(得分:3)

经过几个小时后,我终于找到了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开始,一切似乎都是最近的变化。

答案 1 :(得分:1)

如果您的服务器默认不允许OPTIONS,您可以添加一个显式处理程序:

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

另一个可能的问题是你不会产生以下标题的效果:

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

规范允许*通配符值,但浏览器尚不支持它们。所以你必须做的是,在那些值中明确指定允许的方法和标题:

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