最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Spring Boot POST request returning 405 in a Dockerized React + Spring Todo App - Stack Overflow

programmeradmin4浏览0评论

I'm building a todo app with a Spring Boot backend and a React frontend. The backend provides the API, and the project is containerized using Docker.

My @GetMapping requests work correctly, but my @PostMapping method does not seem to be working at all. When I try to add a new todo item, I get a 405 Method Not Allowed error. Additionally, I don't see any logs in Spring, which makes me think the request isn't even reaching the backend.

What could be causing this issue? Any help would be appreciated!

Forum Component:

const handleSubmit = async (e) => {
    e.preventDefault();

    if (title.trim() === "") return;

    try {
      const response = await fetch(`${baseUrl}/api/todos/`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ title }),
      });

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }

      const newTodo = await response.json();
      onAdd(newTodo);
      setTitle("");
    } catch (error) {
      console.error("There was an error adding the todo:", error);
    }
  };

Controller Mappings:

@RestController
@RequestMapping("/api")
public class TodoController {

    private static final Logger logger = LoggerFactory.getLogger(TodoController.class);

    @Autowired
    private TodoService todoService;

    @GetMapping("/todos/")
    public ResponseEntity<List<TodoResponse>> getAllTodos() {
        logger.info("GET request to /api/todos");
        List<TodoResponse> response = todoService.getTodos();
        return ResponseEntity.ok(response);
    }

    @GetMapping("/todos/{id}")
    public ResponseEntity<TodoResponse> getTodoById(@PathVariable Long id) {
        logger.info("GET request to /api/todos/{}", id);
        TodoResponse response = todoService.getToDoById(id);
        return ResponseEntity.ok(response);
    }

    @PostMapping("/todos/")
    public ResponseEntity<TodoResponse> addTodo(@RequestBody TodoRequest request) {
        logger.info("POST request to /api/todos with body: {}", request);
        TodoResponse response = todoService.createToDo(request);
        return ResponseEntity.ok(response);
    }

    @PutMapping("/todos/{id}")
    public ResponseEntity<TodoResponse> updateTodo(@PathVariable Long id, @RequestBody TodoRequest request) {
        logger.info("PUT request to /api/todos/{} with body: {}", id, request);
        TodoResponse response = todoService.updateToDo(id, request);
        return ResponseEntity.ok(response);
    }

    @DeleteMapping("/todos/{id}")
    public ResponseEntity<Void> deleteTodo(@PathVariable Long id) {
        logger.info("DELETE request to /api/todos/{}", id);
        todoService.deleteToDoById(id);
        return ResponseEntity.noContent().build();
    }
}

Vite proxy config:

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import dns from "node:dns";

dns.setDefaultResultOrder("verbatim");

// /config/
export default defineConfig({
  plugins: [react()],
  server: {
    proxy: {
      "/api/todos/": {
        target: "http://build-api:8080",
        changeOrigin: true,
        secure: false,
      },
    },
  },
});

Docker Compose file:

services:
  # Creates the database service.
  db:
    # The image being used. Currently the "lastest" postgres image.
    image: postgres
    # Restart on error unless manually stopped.
    restart: unless-stopped
    environment:
      # Sets the password for the database user.
      POSTGRES_PASSWORD: secret
    #Exposes port 5432 to the host.
    ports:
      - 5432:5432
    # Use the backend container network.
    networks:
      - backend
    # Create persistent data by saving to a docker volume.
    volumes:
      - ghg-data:/var/lib/postgresql/data
  # For building the api service image
  build-api:
    # names the service.
    image: spring-api
    # Where the source code and Dockerfile live.
    depends_on:
      - db
    build:
      context: ./api/
      dockerfile: ./Dockerfile
    ports:
      - 8080:8080
    # Set this so spring can find the db as it differs from on localhost.
    environment:
      SPRING_DATASOURCE_URL: jdbc:postgresql://db:5432/postgres
    networks:
      - backend
  client-nginx:
    image: client-nginx
    build:
      context: ./frontend/
      dockerfile: Dockerfile
    networks:
      - backend
    ports:
      - 8081:80
  client-vite:
    image: client-vite
    build:
      context: ./frontend/
      dockerfile: Dockerfile-vite
    volumes:
      - type: bind
        source: ./frontend/
        target: /usr/src/app/
      - type: volume
        target: /usr/src/app/node_modules
      - type: bind
        source: ./frontend/vite.config.js
        target: /usr/src/app/vite.config.js
    networks:
      - backend
    ports:
      - 5173:5173
# Creates the volume.
volumes:
  ghg-data:
# Creates the network. Can later create a frontend network to seperate
# the frontend and backend.
networks:
  backend:
  frontend:
发布评论

评论列表(0)

  1. 暂无评论