From b58cb03387f4296890c2a86fce29340eb265ab5c Mon Sep 17 00:00:00 2001 From: Pavel Solovev Date: Fri, 3 Jul 2026 16:23:27 +0300 Subject: [PATCH] Add support for the HTTP QUERY method (RFC 10008) --- CHANGELOG.md | 6 +++++- guides/routing.md | 2 +- lib/phoenix/router.ex | 2 +- lib/phoenix/test/conn_test.ex | 2 +- mix.exs | 2 +- test/phoenix/router/routing_test.exs | 8 ++++++++ 6 files changed, 17 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17cc96aae9..c35a0bd08a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Changelog for v1.9 -Nothing, so far. +This release requires Plug v1.21+. + +### Enhancements + + * [Router] Add the `query` macro for routing HTTP QUERY (RFC 10008) requests ([#6737](https://github.com/phoenixframework/phoenix/pull/6737)) ## v1.8 diff --git a/guides/routing.md b/guides/routing.md index b7efc0b24f..3486321253 100644 --- a/guides/routing.md +++ b/guides/routing.md @@ -56,7 +56,7 @@ Inside the scope block, however, we have our first actual route: get "/", PageController, :home ``` -`get` is a Phoenix macro that corresponds to the HTTP verb GET. Similar macros exist for other HTTP verbs, including POST, PUT, PATCH, DELETE, OPTIONS, CONNECT, TRACE, and HEAD. +`get` is a Phoenix macro that corresponds to the HTTP verb GET. Similar macros exist for other HTTP verbs, including QUERY, POST, PUT, PATCH, DELETE, OPTIONS, CONNECT, TRACE, and HEAD. > #### Why the macros? {: .info} > diff --git a/lib/phoenix/router.ex b/lib/phoenix/router.ex index 7313ecad65..a32b0db5a1 100644 --- a/lib/phoenix/router.ex +++ b/lib/phoenix/router.ex @@ -292,7 +292,7 @@ defmodule Phoenix.Router do alias Phoenix.Router.{Resource, Scope, Route, Helpers} - @http_methods [:get, :post, :put, :patch, :delete, :options, :connect, :trace, :head] + @http_methods [:get, :query, :post, :put, :patch, :delete, :options, :connect, :trace, :head] @doc false defmacro __using__(opts) do diff --git a/lib/phoenix/test/conn_test.ex b/lib/phoenix/test/conn_test.ex index 9def147398..466c9d4298 100644 --- a/lib/phoenix/test/conn_test.ex +++ b/lib/phoenix/test/conn_test.ex @@ -154,7 +154,7 @@ defmodule Phoenix.ConnTest do |> Conn.put_private(:phoenix_recycled, true) end - @http_methods [:get, :post, :put, :patch, :delete, :options, :connect, :trace, :head] + @http_methods [:get, :query, :post, :put, :patch, :delete, :options, :connect, :trace, :head] for method <- @http_methods do @doc """ diff --git a/mix.exs b/mix.exs index afe9685e85..71d728818e 100644 --- a/mix.exs +++ b/mix.exs @@ -79,7 +79,7 @@ defmodule Phoenix.MixProject do defp deps do [ - {:plug, "~> 1.14"}, + {:plug, "~> 1.21"}, {:plug_crypto, "~> 1.2 or ~> 2.0"}, {:telemetry, "~> 0.4 or ~> 1.0"}, {:phoenix_pubsub, "~> 2.1"}, diff --git a/test/phoenix/router/routing_test.exs b/test/phoenix/router/routing_test.exs index 0818d40ab8..fdc1880618 100644 --- a/test/phoenix/router/routing_test.exs +++ b/test/phoenix/router/routing_test.exs @@ -17,6 +17,7 @@ defmodule Phoenix.Router.RoutingTest do def options(conn, _params), do: text(conn, "users options") def connect(conn, _params), do: text(conn, "users connect") def trace(conn, _params), do: text(conn, "users trace") + def query(conn, _params), do: text(conn, "users query") def not_found(conn, _params), do: text(put_status(conn, :not_found), "not found") def image(conn, _params), do: text(conn, conn.params["path"] || "show files") def move(conn, _params), do: text(conn, "users move") @@ -56,6 +57,7 @@ defmodule Phoenix.Router.RoutingTest do trace("/trace", UserController, :trace) options "/options", UserController, :options connect "/connect", UserController, :connect + query "/query", UserController, :query match :move, "/move", UserController, :move match :*, "/any", UserController, :any @@ -185,6 +187,12 @@ defmodule Phoenix.Router.RoutingTest do assert conn.resp_body == "users trace" end + test "query to custom action" do + conn = call(Router, :query, "/query") + assert conn.status == 200 + assert conn.resp_body == "users query" + end + test "splat arg with preceding named parameter to files/:user_name/*path" do conn = call(Router, :get, "/files/elixir/Users/home/file.txt") assert conn.status == 200