【问题标题】:Can't get PATCH / PUT requests to express API to return a valid json response无法获取 PATCH / PUT 请求以表达 API 以返回有效的 json 响应
【发布时间】:2020-10-31 16:44:17
【问题描述】:

简单的待办事项列表:React 前端,Express 后端。我是 React 新手,在触发一个函数来更新数组中包含的单个待办事项时,我陷入了某种反模式。

我在控制台中记录了请求的结果,您可以在下面看到它。还会分享React代码和Express的,实在不明白哪里出了问题,卡了好久。

在进行 PATCH 调用时,实际上会进行 OPTIONS 调用,如下所示

Request URL: http://ec2-3-11-68-236.eu-west-2.compute.amazonaws.com:3001/3
Request Method: OPTIONS
Status Code: 200 OK
Remote Address: 3.11.68.236:3001
Referrer Policy: no-referrer-when-downgrade

Access-Control-Allow-Headers: *
Access-Control-Allow-Methods: *
Access-Control-Allow-Origin: *
Allow: PATCH,GET,HEAD,DELETE
Connection: keep-alive
Content-Length: 21
Content-Type: text/html; charset=utf-8
Date: Mon, 22 Jun 2020 11:58:53 GMT
ETag: W/"15-jHsDAtM3pLnwtbz4TiFr85EHmew"
X-Powered-By: Express

Provisional headers are shown
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: PATCH
Origin: http://ec2-3-11-68-236.eu-west-2.compute.amazonaws.com:5000
Referer: http://ec2-3-11-68-236.eu-west-2.compute.amazonaws.com:5000/?
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36

之后,使用以下命令进行 PATCH 调用:

Request URL: http://ec2-3-11-68-236.eu-west-2.compute.amazonaws.com:3001/3
Request Method: PATCH
Status Code: 404 Not Found
Remote Address: 3.11.68.236:3001
Referrer Policy: no-referrer-when-downgrade
Access-Control-Allow-Headers: *
Access-Control-Allow-Methods: *
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 0
Date: Mon, 22 Jun 2020 11:58:53 GMT
X-Powered-By: Express

Request Headers
Provisional headers are shown
Accept: application/json
Content-type: application/json
Origin: http://ec2-3-11-68-236.eu-west-2.compute.amazonaws.com:5000
Referer: http://ec2-3-11-68-236.eu-west-2.compute.amazonaws.com:5000/?
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36

Request Payload
{title: "new todo"}
title: "new todo"

我知道OPTIONS调用是为了检查http请求是否合法,但是为什么我的实际PATCH请求包含在OPTIONS调用中(如content-length:21所示),而PATCH请求的内容长度:0?

另外,我不明白为什么我会遇到这种 PATCH 调用中的内容长度为 0,但请求有效负载中有实际内容的行为。

这是 React 代码:

import React, {Component} from 'react';

class App extends Component {

constructor(){
    super();

    this.state = { todos:[],
        currentItem: ''
    }   
    this.handleInputChange = this.handleInputChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.deleteItem=this.deleteItem.bind(this);
    this.updateTodo=this.updateTodo.bind(this);
}


handleInputChange = (e) => this.setState({ currentItem: e.target.value });

handleSubmit(event) {
    event.preventDefault();
    fetch('http://ec2-3-11-68-236.eu-west-2.compute.amazonaws.com:3001/post', {
        method: 'POST',
        headers:{
            'Accept': 'application/json',
            'Content-type': 'application/json'},
        body: JSON.stringify({title: this.state.currentItem})
        })
        .then(res => res.json())
        //.then(data => console.log(data))
        .then(data => {
            this.setState({
                todos: [...this.state.todos, data.todo]
            })
        })
        //console.log(this.state)
}

updateTodo(y){
    fetch('http://ec2-3-11-68-236.eu-west-2.compute.amazonaws.com:3001/' + y, {
        method: 'PATCH',
        headers:{
            'Accept': 'application/json',
            'Content-type': 'application/json'},
        body: JSON.stringify({title: this.state.currentItem}),
        })
        .then(res => console.log(res))
        //.then(data => {
        //  this.setState({
        //      todos: this.state.todos.forEach(
        //          item => {
        //              if(item.key === y){item.title = this.state.currentItem}
        //              })
        //      })
        //  })
    }

deleteItem(x){
    fetch('http://ec2-3-11-68-236.eu-west-2.compute.amazonaws.com:3001/' + x, {
        method: 'DELETE',
        headers:{
            'Accept': 'application/json',
            'Content-type': 'application/json'}
    })
    .then(res => res.json())
    .then(data => {
        this.setState({
            todos: this.state.todos.filter (t => t.key !== x)
        })
    })
}

componentDidMount(){
    fetch('http://ec2-3-11-68-236.eu-west-2.compute.amazonaws.com:3001/list')
    .then(res => res.json())
    .then((todos) => {
        this.setState({todos: todos});
    });
}

render() {
    return(
        <div>
         <h1> Todo List </h1>
        <form onSubmit={this.handleSubmit}>
        <input 
            type ="text"
            value = {this.state.currentItem}
            onChange = {this.handleInputChange}
        />
        <input type="submit" value="ADD TODO" />
         </form>
        <ul>
             {this.state.todos.map((todo) => (
         <li key = {todo.key}> {todo.title} 
         <button onClick = {() => this.deleteItem(todo.key)}>x</button>
         <button onClick = {() => this.updateTodo(todo.key)}>update</button>
         </li>
         ))}
            </ul>
            </div>
        )
}
}
export default App

我认为如果响应包含正确的 json 响应,注释掉的部分会起作用,现在我已经将它们注释掉了,因为我似乎无法正确地发出 PATCH 请求。奇怪的是,正确的待办事项(请求中包含 id 的待办事项)确实得到了正确更新。我也尝试了动词 PUT,输出没有区别。

虽然这是快递代码:

const express = require('express');
const bodyParser = require('body-parser');
const app = express();
var counter = 3
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "*");
res.header("Access-Control-Allow-Methods", "*")
next();
});

var todos = [{key:1, title:'eat'}, {key:2, title:'pray'}, {key:3, title:'love'}];
app.listen(3001, function (err) {
if (err) {
console.error('Cannot listen at port 3001', err);}
console.log('Todo app listening at port 3001');
});

app.use(bodyParser.urlencoded({ extended: false }));
// parse application/json
app.use(bodyParser.json());

//GET the whole todos list
app.get('/list', (req, res) => res.status(200).json(todos));

//POST a new todo to the list
app.post('/post', (req, res) => {
if(!req.body.title) {
  return res.status(400).send({
    success: 'false',
    message: 'title is required'
  });
} 
counter ++;
const todo = {
 key: counter,
 title: req.body.title
}
todos.push(todo);
return res.send({todo})
});

//PUT to UPDATE a single item
app.patch('/:key', (req, res) => {
var title = req.body.title
var key = parseInt(req.params.key, 10);

for (var i = 0; i < todos.length; i++){
    if (todos[i].key === key){
        todos[i].title = title;
        break;
        res.status(200).send({
            success: 'true',
            message: 'Todo updated successfully'
        })
}else {res.status(404, 'The task was not found').send()}
};
});

//GET a single item
app.get('/:key', (req, res) => {
  const key = parseInt(req.params.key, 10);
  todos.map((todo) => {
    if (todo.key === key) {
      return res.status(200).send({todo});
    } 
});
 return res.status(404).send({
   success: 'false',
   message: 'todo does not exist',
  });
});

//DELETE an item by its ID
app.delete('/:key', (req, res) => {
  const key = parseInt(req.params.key, 10);

  todos.map((todo, index) => {
    if (todo.key === key) {
       todos.splice(index, 1);
       return res.status(200).send({
         success: 'true',
         message: 'Todo deleted successfully',
       });
    }
  });
    return res.status(404).send({
      success: 'false',
      message: 'todo not found',
    });

});

module.exports = app;

【问题讨论】:

  • 简而言之,当请求不简单时执行 OPTIONS 调用,这意味着它具有一些自定义标头。它这样做是为了验证是否可以接受带有这些参数的请求。

标签: javascript node.js reactjs


【解决方案1】:

好吧,在您发送状态 200 响应之前,您有 break; 行。看看在res.send 之后移动它是否有帮助。正确的条目得到更新的事实证明执行在那个时候被缩短了。

OPTIONS 请求只是一个 CORS 预检请求,用于查看后端是否接受您的请求来源(以及动词、标头等)。阅读更多here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-16
    • 2017-06-07
    • 2018-11-03
    • 1970-01-01
    • 2021-02-07
    • 1970-01-01
    相关资源
    最近更新 更多