提问者:小点点

无法获取对express API的补丁/PUT请求以返回有效的json响应


简单的待办事项列表:前端反应,后端快速。 我是个新手,在激发函数更新数组中包含的单个todo时,我陷入了某种反模式。

我在控制台中记录了请求的结果,您可以在下面看到它。 我也会分享React代码和Express一个,我真的不明白哪里出了问题,我已经卡住了相当一段时间。

在发出补丁呼叫时,实际上会发出一个选项呼叫,如下所示

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

之后,通过以下方式发出补丁呼叫:

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请求是否合法的一种手段进行的,但为什么我的实际补丁请求包含在OPTIONS调用中(如content-length:21所示),而补丁请求具有content length:0呢?

此外,我不明白为什么我会遇到这种行为,在补丁呼叫中的内容长度为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响应,注释掉的部分将起作用,因为现在我已经注释掉了它们,因为我似乎无法正确地发出补丁请求。 奇怪的是,正确的todo(请求中包含id的todo)确实得到了正确的更新。 我还尝试了动词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;

共1个答案

匿名用户

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

options请求只是一个CORS预执行请求,以查看后端是否接受您的请求源(以及动词,标题等)。 在这里阅读更多。