← Back to list

Http::query() in Laravel 13.19.0: The HTTP Client Now Supports the QUERY Method (RFC 10008)

Ever needed to send a search request with a huge list of filters — say, 20 categories, a date range, several statuses, plus sorting — and…

Developer Awam in CodeX · 2026-07-09 04:05 · 1 claps · 4.6 min read paywalled
#laravel #php #web-development #programming #laravel-framework
Open on Medium ↗
Wiki topics: 💻 · Programming 🌐 · Web Development

Http::query() in Laravel 13.19.0: The HTTP Client Now Supports the QUERY Method (RFC 10008)

Ever needed to send a search request with a huge list of filters — say, 20 categories, a date range, several statuses, plus sorting — and wondered where on earth to put all of it?

You can read the full story for free by clicking here

If you cram it into the query string, the URL turns into a small novel. Some servers and proxies will straight-up reject requests once the URL gets too long. So a lot of teams end up “cheating”: pretending to use POST even though the operation is purely a read, not a write. The side effect is that this search request can't be cached and isn't safe to retry automatically on failure, even though it really should be.

Good news: Laravel 13.19.0 gives this problem an official fix. The HTTP Client now supports the QUERY method through Http::query(), complete with its own testing helpers. Let's break it down.

What Exactly Is the QUERY Method?

QUERY isn't some verb Laravel invented on its own — it comes from an official IETF specification, RFC 10008 ("The HTTP QUERY Method"), now a Proposed Standard. It spent a long time as a working draft under the HTTP working group (draft-ietf-httpbis-safe-method-w-body) before being formally published as an RFC. The idea is simple: a method that's safe and idempotent like GET, but that can carry a request body like POST.

Two key properties worth understanding:

  • Safe — the request doesn’t change any state on the server. Just like GET, it's "asking," not "changing."
  • Idempotent — sending the same request multiple times produces the same result without extra side effects. That’s what makes QUERY safe to retry automatically, or even cache, by infrastructure that understands the verb.

Think of QUERY as "GET that's allowed to bring a suitcase full of stuff," while GET can only bring a small bag (the query string).

Before vs. After

Before Http::query() existed, if you had a complex search payload, you were stuck with two options, neither of them great:

// Option 1: forced into the query string, URL turns into a monster
$response = Http::get('https://api.example.com/search', [
    'categories' => ['tech', 'design', 'business'],
    'date_from' => '2026-01-01',
    'date_to' => '2026-07-01',
    'status' => ['active', 'pending'],
    'sort' => 'created_at',
    // ...and it just keeps growing
]);

// Option 2: "cheating" with POST for something that's really just a read
$response = Http::post('https://api.example.com/search', [
    'categories' => ['tech', 'design', 'business'],
    'date_from' => '2026-01-01',
    'date_to' => '2026-07-01',
]);

The first option quickly hits URL length limits. The second makes a plain read operation show up as a write in your logs, middleware, and monitoring tools — even though nothing on the server actually changed.

After Http::query(), you can send that same complex payload through the body, while staying honest about the fact that this is still a read operation:

$response = Http::query('https://api.example.com/search', [
    'categories' => ['tech', 'design', 'business'],
    'date_from' => '2026-01-01',
    'date_to' => '2026-07-01',
    'status' => ['active', 'pending'],
    'sort' => 'created_at',
]);

On the server side, you just register a route that responds to the QUERY verb:

Route::match(['QUERY'], '/search', function () {
    $categories = request()->input('categories');
    $dateFrom = request()->input('date_from');

    // handle the search as usual
    return Product::query()
        ->whereIn('category', $categories)
        ->whereBetween('created_at', [$dateFrom, request()->input('date_to')])
        ->get();
});

Data that used to be crammed into the URL now sits neatly in the body, while the request still means “just asking,” not “changing something.”

Why This Actually Matters

  • No more URL length limits for complex search or filter payloads, since the data travels through the body instead of the query string.
  • HTTP semantics stay honest. A read operation is recorded as a read — not disguised as a POST, which by convention implies "creating or modifying something."
  • Retries and caching become safer, because the safe and idempotent nature of QUERY lets infrastructure (load balancers, reverse proxies, or internal tooling) treat this request more like a GET than a risky POST that shouldn't be blindly repeated.
  • It aligns with a broader trend across the HTTP ecosystem. GraphQL, Elasticsearch, and several modern APIs have long needed a “query with body” pattern. Laravel now has a native way to do this, without needing to hack around it yourself.

One important note: since QUERY isn't part of the CORS-safelisted method list, cross-origin requests to a QUERY endpoint will trigger a preflight request in the browser — this is explicitly called out in the Security Considerations section of RFC 10008. If you're calling this endpoint from the frontend, make sure your server is ready to handle that preflight. Also, even though it's now an official RFC, real-world adoption is still fresh, so not every piece of infrastructure (older proxies, some load balancers, or third-party services) automatically understands the QUERY method yet — worth checking if you're running this in a production environment with several network layers involved.

Bonus: Testing Helpers Came Along Too

The same release also adds query() and queryJson() as testing helpers, so you can test routes that respond to QUERY just as easily as you'd test with delete() or deleteJson(), which you're probably already familiar with.

Here’s a full example:

// routes/web.php
Route::match(['QUERY'], '/search', function () {
    return response()->json([
        'filter' => request()->input('filter'),
    ]);
});
// tests/Feature/SearchTest.php
use Illuminate\Foundation\Testing\RefreshDatabase;

it('can search products using the QUERY method', function () {
    $this->queryJson('/search', [
        'filter' => 'active',
    ])->assertOk()
      ->assertJson([
          'filter' => 'active',
      ]);
});

This helper works by placing your test data into the request body, following the exact same pattern you already know from other verb-specific helpers. You don’t need to learn a new API to write these tests — just swap in query() or queryJson(), and everything else follows the same pattern you're used to when writing HTTP tests in Laravel.

When Should You Actually Use QUERY Instead of GET or POST?

To keep things simple, here’s a quick guide:

  • Use **GET** when your search parameters are short and simple — the query string handles it just fine.
  • Use **QUERY** when you need to send complex or lengthy search criteria, but the operation is still a pure read with no side effects.
  • Use **POST** when the goal is actually creating, modifying, or triggering a side effect on the server — not just asking a question.

Wrapping Up

A small feature like Http::query() is easy to skim past if you only glance at the changelog, but it makes a real difference for teams that regularly deal with complex search or filtering endpoints. No more hacking around with POST for what's really a read operation, and no more worrying about URLs getting too long.

If your project deals a lot with search or filtering endpoints — especially ones talking to third-party APIs that already support QUERY — this is one feature in 13.19.0 that's worth trying out right away.

Official references: Laravel Framework Release v13.19.0, PR #60663 and #60662, and RFC 10008 — The HTTP QUERY Method.


메타데이터
post_id
166abe083fba
slug
http-query-in-laravel-13-19-0-the-http-client-now-supports-the-query-method-rfc-10008-166abe083fba
url
https://medium.com/codex/http-query-in-laravel-13-19-0-the-http-client-now-supports-the-query-method-rfc-10008-166abe083fba
canonical_url
https://medium.com/codex/http-query-in-laravel-13-19-0-the-http-client-now-supports-the-query-method-rfc-10008-166abe083fba
author_url
https://medium.com/@developerawam
status
ok
fetched_at
2026-07-10 11:40:45