You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js本地服务器Axios POST请求报错排查求助

Node.js本地服务器POST请求问题排查

我是Node.js新手,在使用Axios向Node.js本地服务器发送POST请求时出现错误,无法定位问题根源。

错误说明

错误截图显示请求返回400状态码,同时存在跨域配置缺失、后端逻辑缺陷等问题。

后端代码(Server.js)

const http = require('http');

class InMemoryDatabase {
    constructor() {
      this.data = [];
    }
  
    // 向数据库添加对象
    add(object) {
      this.data.push(object);
    }
  
    // 更新数据库中的对象
    update(id, object) {
      const index = this.findIndexById(id);
      if (index !== -1) {
        this.data[index] = Object.assign(this.data[index], object);
      }
    }
  
    // 删除数据库中的对象
    delete(id) {
      const index = this.findIndexById(id);
      if (index !== -1) {
        this.data.splice(index, 1);
      }
    }
  
    // 获取数据库中所有对象
    getAll() {
      return this.data;
    }
  
    // 根据ID获取数据库中的对象
    getById(id) {
      const index = this.findIndexById(id);
      if (index !== -1) {
        return this.data[index];
      }
    }
  
    // 按筛选条件查询数据库中的对象
    search(filter) {
      return this.data.filter(object => {
        for (const key in filter) {
          if (filter[key] !== object[key]) {
            return false;
          }
        }
        return true;
      });
    }
  
    // 根据ID查找对象在数据库中的索引
    findIndexById(id) {
      return this.data.findIndex(object => object.id === id);
    }
  }

// 创建数据库实例
const db = new InMemoryDatabase();

// 创建Web服务器
const server = http.createServer((req, res) => {
    if (req.method === 'GET' && req.url === '/') {
      // 返回数据库中所有对象的JSON格式数据
      res.setHeader('Content-Type', 'application/json');
      // 添加CORS头
      res.setHeader('Access-Control-Allow-Origin', '*');
      res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
      res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
      res.write(JSON.stringify(db.getAll()));
      res.end();
    } else if (req.method === 'GET' && req.url.startsWith('/object/')) {
      // 根据ID返回单个对象的JSON格式数据
      const id = parseInt(req.url.split('/')[2]);
      const object = db.getById(id);
      if (object) {
        res.setHeader("Content-Type", "application/json, text/plain, */*");
        res.write(JSON.stringify(object));
      } else {
        res.statusCode = 404;
      }
      res.end();
    } else if (req.method === 'POST' && req.url === '/') {
      // 向数据库添加新对象
      let data = '';
      req.on('data', chunk => {
        data += chunk;
      });
      req.on('end', () => {
        try {
          const object = JSON.parse(data);
          const id = db.add(object);
          res.setHeader("Content-Type", "application/json, text/plain, */*");
          res.setHeader('Location', `/object/${id}`);
          res.statusCode = 201;
          res.write(JSON.stringify({ id }));
        } catch (err) {
          res.statusCode = 400;
        }
        res.end();
      });
    } else {
      res.statusCode = 404;
      res.end();
    }
  });

// 在8080端口启动Web服务器
server.listen(8080, () => {
  console.log('Web服务器已在8080端口启动');
});

前端代码(App.js)

import React, { useState, useEffect } from 'react';
import axios from 'axios';
import { Table, Button, Modal, Form } from 'react-bootstrap';

function App() {
  const [data, setData] = useState([]);
  const [showModal, setShowModal] = useState(false);
  const [formData, setFormData] = useState({
    name: '',
    email: '',
    phone: ''
  });

  useEffect(() => {
    axios.get("http://localhost:8080").then((response) => {
      console.log(response.data)
      setData(response.data);
    })
  }, []);

  const handleFormChange = (event) => {
    const { name, value } = event.target;
    setFormData((prevFormData) => ({
      ...prevFormData,
      [name]: value
    }));
  };

  const handleFormSubmit = (event) => {
    event.preventDefault();
    axios
      .post("http://localhost:8080", {
        name: "melvin",
        email: "test",
        phone: "test",
      })
      .then((response) => {
        console.log(response.data);
      })
      .catch((error) => console.log(error));
    setShowModal(false);
  };

  const handleDelete = (id) => {
    axios.delete(`/api/data/${id}`).then(() => {
      setData(data.filter((item) => item.id !== id));
    });
  };

  return (
    <div>
      <Table striped bordered hover>
        <thead>
          <tr>
            <th>Name</th>
            <th>Email</th>
            <th>Phone</th>
            <th>Action</th>
          </tr>
        </thead>
        <tbody>
          {data.map((item) => (
            <tr key={item.id}>
              <td>{item.name}</td>
              <td>{item.email}</td>
              <td>{item.phone}</td>
              <td>
                <Button variant="danger" onClick={() => handleDelete(item.id)}>
                  Delete
                </Button>
              </td>
            </tr>
          ))}
        </tbody>
      </Table>
      <Button variant="primary" onClick={() => setShowModal(true)}>
        Add Item
      </Button>
      <Modal show={showModal} onHide={() => setShowModal(false)}>
        <Modal.Header closeButton>
          <Modal.Title>Add Item</Modal.Title>
        </Modal.Header>
        <Modal.Body>
          <Form onSubmit={handleFormSubmit}>
            <Form.Group controlId="name">
              <Form.Label>Name</Form.Label>
              <Form.Control
                type="text"
                name="name"
                placeholder="Enter name"
                value={formData.name}
                onChange={handleFormChange}
                required
              />
            </Form.Group>
            <Form.Group controlId="email">
              <Form.Label>Email</Form.Label>
              <Form.Control
                type="email"
                name="email"
                placeholder="Enter email"
                value={formData.email}
                onChange={handleFormChange}
                required
              />
            </Form.Group>
            <Form.Group controlId="phone">
              <Form.Label>Phone</Form.Label>
              <Form.Control
                type="text"
                name="phone"
                placeholder="Enter phone number"
                value={formData.phone}
                onChange={handleFormChange}
                required
              />
            </Form.Group>
            <Button variant="primary" type="submit">
              Add
            </Button>
          </Form>
        </Modal.Body>
      </Modal>
    </div>
  );
}

export default App;

问题修复点

后端(Server.js)

  1. 全局配置CORS:当前仅GET请求设置了CORS头,需在所有响应前统一配置,并处理OPTIONS预检请求:
// 全局设置CORS头
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');

// 处理OPTIONS预检请求
if (req.method === 'OPTIONS') {
  res.writeHead(200);
  res.end();
  return;
}
  1. 修复add方法返回值:当前add方法未返回ID,导致后续逻辑获取undefined,修改为自动生成唯一ID并返回:
add(object) {
  const newObject = { id: Date.now(), ...object }; // 用时间戳生成唯一ID
  this.data.push(newObject);
  return newObject.id;
}
  1. 修正Content-Type格式:所有返回JSON的接口,Content-Type应设为application/json,而非多值拼接格式:
res.setHeader('Content-Type', 'application/json');
  1. 完善错误处理:JSON解析失败时,返回明确的错误信息:
catch (err) {
  res.statusCode = 400;
  res.setHeader('Content-Type', 'application/json');
  res.write(JSON.stringify({ error: 'JSON格式无效' }));
}
  1. 添加DELETE接口支持:补充删除逻辑的后端实现:
else if (req.method === 'DELETE' && req.url.startsWith('/object/')) {
  const id = parseInt(req.url.split('/')[2]);
  db.delete(id);
  res.statusCode = 204;
  res.end();
}

前端(App.js)

  1. 使用用户输入的表单数据:替换handleFormSubmit中硬编码的测试数据,使用用户输入的formData:
axios.post("http://localhost:8080", formData)
  1. 修复删除请求地址:后端删除接口路径为/object/:id,修正请求地址:
axios.delete(`http://localhost:8080/object/${id}`)
  1. POST成功后更新前端数据:在POST请求回调中重新拉取数据,更新页面列表:
.then((response) => {
  console.log(response.data);
  // 重新获取数据更新列表
  axios.get("http://localhost:8080").then(res => setData(res.data));
})

内容的提问来源于stack exchange,提问作者melvin debot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 23:22:39