无法使用 PUT 方法通过 CORS 和 Express 发送数据

Posted

技术标签:

【中文标题】无法使用 PUT 方法通过 CORS 和 Express 发送数据【英文标题】:Unable To use PUT method to send data via CORS with Express 【发布时间】:2018-04-18 00:41:48 【问题描述】:

我正在使用端口 8080 上的 RESTful API 在端口 4000 上开发简单的 Web 应用程序。我使用 cors 包进行了 Express 设置,并且我似乎从 OPTIONS 请求中发送了正确的标头,见下文:

X-Powered-By: Express
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE
Vary: Access-Control-Request-Headers
Access-Control-Allow-Headers: content-type
Content-Length: 0

返回状态为 204 ok。然后我在 FF Network 控制台中看到 PUT 请求,大约 45 秒后出现请求标头:

PUT /movies/updatemovie/59f4ee92be4becd967a573ca HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json
Referer: http://localhost:4000/movies
Content-Length: 151
Origin: http://localhost:4000
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache

请求参数为:

documentID=59f4ee92be4becd967a573ca&title=Captain%20America%3A%20Civil%20UnWar&release=2016&score=9&reviewer=%20Janet%20Garcia&publication=%20MoviesNow

Chrome 显示 PUT 在 4 分钟后失败。

数据没有发布到 Mongo,我也没有从服务器得到任何响应。

以下是相关代码:

网络应用

$(".panel").each(function (index) 
    if ($(this).find("input[name = 'update']").is(":checked")) 
        updatedDocument = 
            documentID: $(this).data("id"),
            title: $(this).find("input#name").val(),
            release: $(this).find("input#release").val(),
            score: $(this).find("input#score").val(),
            reviewer: $(this).find("input#reviewer").val(),
            publication: $(this).find("input#publication").val()
        ;
        JSON.stringify(updatedDocument);
        console.log(Object.values(updatedDocument));
     // end if
); // .each

// Now we have the document stored in JSON object, so lets form 
// an AJAX req and grab the updated data from our document and send
// a PUT to our API endpoint
$.ajax(
    type: 'PUT',
    data: updatedDocument,
    url: 'http://localhost:8080/movies/updatemovie/' + updatedDocument.documentID,
    dataType: 'JSON',
    contentType: 'application/json'
).done(function (response) 
    // Check for successful (blank) response
    if (response.msg === '') 
        // do nothing
    
    else 
        alert('Error: ' + response.msg);
    
); // end .done

API

/*
 * Put to Update movie.
 */
router.options('updatemovie/:id', cors());  
router.put('/updatemovie/:id', cors(), function(req, res) 
    const db = req.db;
    console.log(req.params.id);
    console.log(req.body.publication);

    const movieCollection = db.get("movies");
    const movieToUpdate = req.params.id; // Assign collection document id from url :id value
    const movieTitle = req.body.title;
    const movieRelease = req.body.release;
    const movieScore = req.body.score;
    const movieReviewer = req.body.reviewer;
    const moviePublication = req.body.publication;

     // Update the movie document from PUT info
    movieCollection.update('_id' : movieToUpdate, 
        
            $set: 
              title: movieTitle,
              release: movieRelease,
              score: movieScore,
              reviewer: movieReviewer,
              publication: moviePublication
            
        ,
        function(err)  
            res.send((err === null) ? msg: '' : msg: err);
        ); // movieCollection .update

);

我从 API 中的 console.logs 中一无所获。欢迎提出任何建议。

更新:通过从 APP contentType: application/JSON 中删除行,现在一切正常。我以为我想将数据作为 JSON 发送到我的 API?任何有任何想法或意见的人都非常欢迎。

【问题讨论】:

【参考方案1】:

您没有以 JSON 格式发送数据。您已将content-type 标头设置为application/json,但数据仍将编码为application/x-www-form-urlencoded。要使用 jQuery 发送 JSON 数据,您需要自己对其进行编码:

data: JSON.stringify(updatedDocument),

在服务器上,您需要一个合适的bodyParser 配置:

app.use(bodyParser.json());

或:

app.use(express.json());

当您删除contentType: 'application/json' 行时,该标头会恢复到其默认值application/x-www-form-urlencoded。这与数据的格式相匹配,并且可能您已将 app.use(bodyParser.urlencoded())app.use(express.urlencoded()) 配置为解析该数据。由于您的数据是一个扁平的字符串/字符串数据结构,因此您选择哪种格式并不重要,您最终会在res.body 中得到相同的值。

【讨论】:

是的,完全正确。感谢您的意见。 我试图将更新的 movieCollection 文档作为 JSON w/res.json(movieCollection) 而不是 res.send(err) 发送回,但我无法发送。响应为空。您对此有何建议?

以上是关于无法使用 PUT 方法通过 CORS 和 Express 发送数据的主要内容,如果未能解决你的问题,请参考以下文章

无法在 JQuery 1.6.4 中使用 CORS 进行 PUT/POST/DELETE HTTP 调用

无法使 PUT 方法工作(Express & Angular)

VB.NET Web API CORS PUT 预检 405 错误

无服务器和 PUT 命令的 CORS 问题

AJAX POST、PUT 和 DELETE 工作正常,但 GET 被 CORS 阻止

Angular PUT 请求通过 SSL 被禁止