使用Fetch API解析的POST请求不起作用

时间:2017-09-15 15:50:53

标签: node.js post cors fetch-api restify

我遇到一些重大问题,理解为什么Fetch API不允许我向我的restify服务器发送POST请求。

我有一个基本的restify服务器,其路由接收/login上的POST请求。

如果我使用Postman或HTTPRequester进行测试,这条路线可以完美地运行,但是当我使用fetch API在浏览器应用程序上测试时,我得到以下错误(在Chrome中):

OPTIONS http://localhost:1337/login 405 (Method Not Allowed)

Fetch API cannot load http://localhost:1337/login. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 405. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

两个问题

  1. 我在请求中专门使用了POSt方法,为什么突然选择OPTIONS?
  2. 我已经在我的服务器上设置了Access-Control-Allow-Origin: *
  3. 编辑:我使用restify v5.2.0

    我的服务器应用

    const restify = require('restify');
    const app = restify.createServer({
        'name': 'API Token Test',
        'version': '1.0.0'
    });
    
    app.use(restify.plugins.acceptParser(app.acceptable));
    app.use(restify.plugins.bodyParser());
    app.use(restify.plugins.jsonp());
    
    app.use((req, res, next) => {
    	res.header('Access-Control-Allow-Origin', '*');
    	res.header('Access-Control-Allow-Headers', 'X-Requested-With');
    	return next();
    });
    
    app.post('/login', (req, res) => {
        db.execute('SELECT idusers, password FROM users WHERE username = ?', [req.body.username], (selError, rows) => {
            if (passwordHash.verify(req.body.password, rows[0].password)) {
                crypto.randomBytes(256, (err, buf) => {
                    if (err) return res.status(500).end();
                    else {
                        const token = buf.toString('hex');
                        db.execute('INSERT INTO accesstokens SET userid = ?, token = ?', [rows[0].idusers, token], (insError) => {
                            if (insError) return res.status(500).end();
                            else return res.send({ "AccessToken": token });
                        });
                    }
                });
            } else {
                res.status(401).end();
            }
        });
    });
    
    app.listen(1337);

    (我遗漏了mysql的东西和crypto / password-hash -requires,这与问题无关)

    我的客户端脚本

    (() => {
        document.addEventListener('DOMContentLoaded', () => {
            const form = document.querySelector('.loginForm');
    
            form.onsubmit = () => {
                const data = JSON.stringify({
                    'username': form.username.value,
                    'password': form.password.value
                });
    
                let headers = new Headers();
                headers.set('Accept', 'application/json');
                headers.set('Content-Type', 'application/json');
                headers.set('Content-Length', data.length);
    
    
                fetch('http://localhost:1337/login', {
                    'method': 'POST',
                    'headers': headers,
                    'mode': 'cors',
                    'cache': 'default',
                    'body': data
                })
                    .then((result) => result.json())
                    .then((data) => {
                        console.log(data);
                        localStorage.setItem('token', data);
                    })
                    .catch((err) => {
                        console.log(err);
                    });
    
                return false;
            };
        });
    })();

1 个答案:

答案 0 :(得分:1)

自从解析v5.x以来,所有CORS支持都已移至this module

安装restify-cors-middleware并将以下内容添加到我的应用程序中:

const corsMiddleware = require('restify-cors-middleware');
const cors = corsMiddleware({
    'origins': ['*']
});
app.pre(cors.preflight);
app.use(cors.actual);