daisuzz.log

【Spring Boot】ThymeleafからのPOSTリクエストをPUT/DELETEで受け取る方法

背景

Spring Bootでは@PutMapping@DeleteMappingなどを使うことでPUT/DELETEメソッドのHTTPリクエストを受け取ることができます。 一方でHTML5では、PUT/DELETEメソッドを送信することができないため、直接HTMLからサーバにリクエストを投げる場合には、HTMLからPOSTリクエストを送り、サーバ側でPUT/DELETEに変換する必要があります。

今回は、Spring BootとThyemeleafを使ったアプリケーションで、POSTリクエストをPUT/DELETEに変換する方法を説明します。

環境

  • Kotlin 1.3
  • Spring Boot 2.3.4.RELEASE

方法

HTML側の設定

HTML側は、formタグのth:methodにputもしくはdeleteを設定します。

<form th:action="@{/todo/{id}(id=${todo.getId()})}" th:method="delete">
    <button type="submit">delete</button>
</form>

実際にレンダリングされると、以下のように_methodというhiddenパラメータをPOSTリクエストで送信するようになります。

<form action="/todo/1" method="post">
  <input type="hidden" name="_method" value="delete">
  <button type="submit" class="btn btn-primary">delete</button>
</form>

サーバ側の設定

Spring Bootで作成したController側では、PUT/DELETEで実行させたいハンドラを実装します。

@Controller
@RequestMapping
class TodoController(private val todoDeleteService: TodoDeleteService) {

    // 省略

    @DeleteMapping("todo/{id}")
    fun delete(@PathVariable id: String, modelAndView: ModelAndView): ModelAndView {

        todoDeleteService.deleteTodo(id)
        modelAndView.viewName = "redirect:/"
        return modelAndView
    }
}

次に、HTMLから送られた_methodというhiddenパラメータを含むPOSTリクエストを、このDELETE用のハンドラに変換する処理を行うHiddenHttpMethodFilterを有効化します。 Spring Boot 2.2系からはHiddenHttpMethodFilterがデフォルトで無効になっているので、設定ファイルに以下を追加します。

spring.mvc.hiddenmethod.filter.enabled=true

Spring MVCの設定をカスタマイズするために, WebMvcConfigurationSupportを継承したConfigurationクラスを利用している場合は、 設定ファイルから有効化する代わりに、以下のように自前でHiddenHttpMethodFilterインスタンスをBeanに登録しておきます。

@Configuration
class ApplicationConfiguration : WebMvcConfigurationSupport() {

    // 省略

    // PUT, DELETEメソッドに変換するServletFilterをBeanとして設定
    @Bean
    fun hiddenHttpMethodFilter(): FilterRegistrationBean<HiddenHttpMethodFilter> {
        val filterRegistrationBean = FilterRegistrationBean(HiddenHttpMethodFilter())
        filterRegistrationBean.urlPatterns = listOf("/*")
        return filterRegistrationBean
    }
}

以上をおこなうことで、HTMLからのPOSTリクエストをPUT/DELETEメソッドに変換して、対応するハンドラを実行させることができます。

参考

Web on Servlet Stack

Spring Boot Reference Documentation

java - Spring Boot how to use HiddenHttpMethodFilter - Stack Overflow