405 METHOD_NOT_ALLOWED

405 METHOD_NOT_ALLOWED

HTML form 태그 사용시 발생한 문제


🚨 문제


Spring WebFlux를 학습하다 마주친 문제이다.

에러 메시지 그대로 해당 URI는 GET 방식의 HTTP 메서드를 지원하지 않는다는 의미이다.


image


Sun Jan 09 18:19:47 KST 2022
[d6491d4c-11, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:57273] There was an unexpected error (type=Method Not Allowed, status=405).
Request method 'GET' not supported
org.springframework.web.server.MethodNotAllowedException: 405 METHOD_NOT_ALLOWED "Request method 'GET' not supported"
	at org.springframework.web.reactive.result.method.RequestMappingInfoHandlerMapping.handleNoMatch(RequestMappingInfoHandlerMapping.java:181)
	Suppressed: The stacktrace has been enhanced by Reactor, refer to additional information below: 
Error has been observed at the following site(s):
	*__checkpoint ⇢ org.springframework.boot.web.reactive.filter.OrderedHiddenHttpMethodFilter [DefaultWebFilterChain]
	*__checkpoint ⇢ HTTP GET "/carts/items/61daa8af245e0001a2670b47" [ExceptionHandlingWebHandler]
Original Stack Trace:
		at org.springframework.web.reactive.result.method.RequestMappingInfoHandlerMapping.handleNoMatch(RequestMappingInfoHandlerMapping.java:181)

🚧 원인


HTML의 form태그는 GETPOST만 지원한다고 한다.

헌데, 나는 form태그에 DELETE 메서드를 사용했고, HTML이 이것을 인식하지 못해 결과적으로 DELETE가 아닌 GET으로 요청이 발생했고, 해당 URI로 요청을 받는 컨트롤러는 작성돼있지 않았기 때문에 발생한 문제로 추측된다.

HTML을 만져본지 몇 달 지났더니 아리송하다.


<form method="delete" th:action="@{'/carts/items/'+${item.id}}">
    <input type="submit" value="Delete from Cart"/>
</form>


@Controller
@RequiredArgsConstructor
@RequestMapping("/carts")
class CartController {
    private final CartManager cartManager;

    @GetMapping
    public Mono<Rendering> viewCart() {
        return cartManager.viewCart();
    }

    @GetMapping("/items")
    public Mono<Rendering> search(
        @RequestParam(required = false) String itemName,
        @RequestParam boolean useAnd
    ) {
        return cartManager.viewCart(itemName, useAnd);
    }

    @PostMapping("/items/{itemId}")
    public Mono<String> addToCart(@PathVariable String itemId) {
        return cartManager.addItemToCart("MyCart", itemId)
            .thenReturn("redirect:/carts");
    }

    // 문제 발생 부분
    @DeleteMapping("/items/{itemId}")
    public Mono<String> deleteFromCart(@PathVariable String itemId) {
        return cartManager.deleteFromCart("MyCart", itemId)
            .thenReturn("redirect:/carts");
    }
}


✅ 해결


form 태그의 메서드를 POST로 변경해주고, form 태그 안에 하기와 같은 hidden input 태그를 추가한다.


<form method="post" th:action="@{'/carts/items/'+${item.id}}">
    <input type="hidden" name="_method" value="delete">
    <input type="submit" value="Delete from Cart"/>
</form>


일반적인 HTML을 사용한다면 여기서 끝날 것 같은데, 나는 타임리프(Thymeleaf)웹플럭스(WebFlux)를 사용하였으므로 하기의 설정을 추가해주었다.


# file: 'application.yaml'
spring:
  webflux:
    hiddenmethod:
      filter:
        enabled: true



© 2022. All rights reserved.