<rss version="2.0">
  <channel>
    <title>Meet Gor - Tag: http</title>
    <link>https://www.meetgor.com</link>
    <description>Posts tagged with http</description>
    <language>en-us</language>
    <pubDate>Sat, 10 Oct 2026 09:08:39 UTC</pubDate>
    <item>
      <title>HTTP QUERY Method</title>
      <link>https://www.meetgor.com/posts/http-query-method</link>
      <description>Exploring the new HTTP Query method with first principles, what is the need for new method, and where it sits. We explore the limitations of GET and the unintuitive use of POST methods for filtering</description>
      <pubDate>Mon, 22 Jun 2026 00:00:00 UTC</pubDate>
      <content>## Why a new method?&#xA;-----------------&#xA;&#xA;We all know and love the 5 HTTP Methods right? GET, POST, PATCH, PUT, DELETE. Some of us even know a couple more with OPTIONS and HEAD. Then you might ask, why is there a need for another method like QUERY. Well, let me explain with an example and why it makes sense for HTTP to have a another method.&#xA;&#xA;### Let&#39;s create an API&#xA;&#xA;Of course, its HTTP, so we understand that we need to interact with the resources on the server. The best understandable example is creating an API. Let&#39;s create a simple API for a Blog. I know its a simple example, but developer (me) have the knack to make simple problems complex, or I should say users force into making the requirements complex. Whatever you think it is. I would start by creating a simple blog API that does CRUD for posts.&#xA;&#xA;So, here&#39;s the simple spec:&#xA;&#xA;```&#xA;POST   /posts&#xA;GET    /posts&#xA;GET    /posts/{id}&#xA;PATCH  /posts/{id}&#xA;DELETE /posts/{id}&#xA;```&#xA;&#xA;Everything looks fine so far.&#xA;&#xA;But we haven&#39;t defined what a Post actually looks like so, let&#39;s define one&#xA;&#xA;```json&#xA;{&#xA;  &#34;id&#34;: 1,&#xA;  &#34;title&#34;: &#34;Understanding HTTP Methods&#34;,&#xA;  &#34;content&#34;: &#34;The core HTTP methods are GET.....&#34;,&#xA;  &#34;author&#34;: &#34;Meet Gor&#34;,&#xA;  &#34;tags&#34;: [&#34;http&#34;, &#34;web&#34;],&#xA;  &#34;status&#34;: &#34;published&#34;,&#xA;  &#34;published_at&#34;: &#34;2026-06-22T10:00:00Z&#34;&#xA;}&#xA;```&#xA;&#xA;But users rarely stop at &#34;give me all posts.&#34;&#xA;&#xA;They want, I want your &#34;TIL&#34; posts, oh no maybe just &#34;articles&#34;, or just &#34;newsletter&#34;. Well. Now we need to add &#34;type&#34; as the field to sort out different types of articles.&#xA;&#xA;```json&#xA;{&#xA;  &#34;id&#34;: 1,&#xA;  &#34;title&#34;: &#34;Understanding HTTP Methods&#34;,&#xA;  &#34;content&#34;: &#34;The core HTTP methods are GET.....&#34;,&#xA;  &#34;author&#34;: &#34;Meet Gor&#34;,&#xA;  &#34;type&#34;: &#34;article&#34;,&#xA;  &#34;tags&#34;: [&#34;http&#34;, &#34;web&#34;],&#xA;  &#34;status&#34;: &#34;published&#34;,&#xA;  &#34;created_at&#34;: &#34;2026-06-22T10:00:00Z&#34;,&#xA;  &#34;published_at&#34;: &#34;2026-06-22T10:00:00Z&#34;&#xA;}&#xA;```&#xA;&#xA;Now you can say, it looks better and more extendable right? for now at least it does maybe. The type could be an enum in the api spec like&#xA;&#xA;-   Article&#xA;-   TIL (today I learnt)&#xA;-   Newsletter&#xA;-   Thoughts&#xA;-   Link Post&#xA;-   Dev blog&#xA;-   Review&#xA;Etc....&#xA;&#xA;But the point is. It could be one of some of the values, and the other end of it is tags, they could be many of some values.&#xA;&#xA;Now, we can support filtering of those on the `GET /posts` method since that is where we list out all the posts.&#xA;&#xA;Lets get all the published newsletter type posts&#xA;&#xA;```http&#xA;GET /posts?status=published&amp;type=newsletter&#xA;```&#xA;&#xA;That is ideal. But this is a blog api. People can go crazy here:&#xA;&#xA;```http&#xA;GET /posts?status=published&amp;type=newsletter&amp;tags=python&amp;sort=-published_at&#xA;```&#xA;&#xA;We&#39;ll have to support sorting, custom filters for tags and things like that. It can get messy pretty soon.&#xA;&#xA;So. Let&#39;s create a separate endpoint for filtering post, it makes it isolated and clean. At least that&#39;s what I would think, if searching and filtering is very specific and needed all the time. To create a separate filter/query endpoint for that resource(s)&#xA;&#xA;### Let&#39;s add an endpoint to filter things&#xA;&#xA;That should be straight forward as :&#xA;&#xA;```http&#xA;GET /posts/search?&#xA;```&#xA;&#xA;This will make it explicit that we are searching for certain resource in this case &#34;posts&#34;&#xA;&#xA;Now.&#xA;&#xA;We simply do what we did before, we allow query parameters to filter the fields like so:&#xA;&#xA;```http&#xA;GET /posts/search?status=published&amp;type=newsletter&amp;tags=python&amp;sort=-published_at&#xA;```&#xA;&#xA;This looks ok, but we can see the query in the URI getting too long. It might create issues right? There is a limit of the number of characters in the URL we can enter, plus it looks wired, too long.&#xA;&#xA;### Limitation of GET&#xA;&#xA;You can see, this is a bit of problem. There is a limitation of 2k characters in the query. I am not saying that this blog post search api will require 2k characters in the uri for filtering post, but think of similar use cases which might require that. Its not a good design but sometimes it becomes inevitable.&#xA;&#xA;So, what is the other option?&#xA;&#xA;Request body.&#xA;&#xA;We can define something like this right?&#xA;&#xA;```http&#xA;GET /posts/search/&#xA;Content-Type: application/json&#xA;&#xA;{&#xA;  &#34;type&#34;: &#34;newsletter&#34;,&#xA;  &#34;status&#34;: &#34;published&#34;,&#xA;  &#34;tags&#34;: &#34;python&#34;,&#xA;  &#34;sort&#34;: &#34;-published_at&#34;&#xA;}&#xA;```&#xA;&#xA;The issue is that if we want to express this into a request body if the request grows, we hit a roadblock. There is no one stopping us from adding a request body in GET but its not defined in the specification. Its not a practical way and a documented way to follow a convention while sending request body in GET method. HTTP does not define semantics for a GET request body. Some clients and servers may support it, but relying on it makes interoperability unpredictable.&#xA;&#xA;So, what is the better way?&#xA;&#xA;### Let&#39;s use POST maybe&#xA;&#xA;Well, this looks inevitable at this point.&#xA;&#xA;Request Query Parameters are too confusing for readers and not practical for complex queries.&#xA;&#xA;If we want to use request body the only option is to use POST method.&#xA;&#xA;```http&#xA;POST /posts/search/&#xA;Content-Type: application/json&#xA;&#xA;{&#xA;  &#34;type&#34;: &#34;newsletter&#34;,&#xA;  &#34;status&#34;: &#34;published&#34;,&#xA;  &#34;tags&#34;: &#34;python&#34;,&#xA;  &#34;sort&#34;: &#34;-published_at&#34;&#xA;}&#xA;```&#xA;&#xA;yes, this looks good right? For the problem development, yes, as a api developer, nope!&#xA;&#xA;POST is not idempotent by definition. Repeating the same POST request may create multiple resources or trigger multiple side effects depending on the server implementation. For instance we send a request first, the resource is created, but the subsequent same request body looks different from the first right? since it depends on the server if it handles duplicates or allows creation of multiple resources.&#xA;&#xA;Also the bigger case for this problem is this&#xA;&#xA;### Using POST to query is unintuitive&#xA;&#xA;POST to query or filter resources doesn&#39;t make sense right? We aren&#39;t creating any resources. So sending a POST request to filter a resource feels a bit unintuitive to me. Since we aren&#39;t creating any resources we should not be sending post requests to filter resources.&#xA;&#xA;Just take a look at this query, if i didn&#39;t add search, how does that distinguish from posts to create and post to search, just adding /`search` to the path makes it easily identifiable.&#xA;&#xA;```http&#xA;POST /posts/&#xA;POST /posts/search/&#xA;&#xA;```&#xA;&#xA;HTTP methods are not just verbs. They communicate intent. That&#39;s why we have PUT and PATCH differently separated and defined. The same is for GET and POST. For people or code generators (LLMs now) need to understand the documentation to make it clear that the POST /posts/search doesn&#39;t create a resource.&#xA;&#xA;But there is no option to send complex data for filtering resources unless we specify a request body.&#xA;&#xA;Until the RFC 10008!&#xA;&#xA;HTTP now has added more method, the QUERY Method. That solves that exact problem of GET being too simple and POST being non-sensicle for filtering or querying data with complex filters.&#xA;&#xA;## QUERY Method&#xA;&#xA;&#xA;The query method bridges the gap between the two methods. GET and POST.&#xA;&#xA;The simplicity of GET request is too limiting.&#xA;&#xA;The usage of POST request is not ideal for filtering.&#xA;&#xA;```http&#xA;QUERY /posts/search/&#xA;&#xA;Content-Type: application/json&#xA;&#xA;{&#xA;  &#34;type&#34;: &#34;newsletter&#34;,&#xA;  &#34;status&#34;: &#34;published&#34;,&#xA;  &#34;tags&#34;: &#34;python&#34;,&#xA;  &#34;sort&#34;: &#34;-published_at&#34;&#xA;}&#xA;```&#xA;&#xA;HTTP has an method verb for that operation `QUERY` to filter/search or literal query the resource.&#xA;&#xA;We can use the body as defined in the specification that can follow a standard like content-type which should be something that the server supports. let&#39;s get into the details of the specification.&#xA;&#xA;## RFC 10008&#xA;&#xA;The request for comments was first started in [2021](https://datatracker.ietf.org/doc/draft-ietf-httpbis-safe-method-w-body/00/) as SEARCH method. But it evolved into QUERY in 4-5 years to become [RFC 10008](https://datatracker.ietf.org/doc/html/rfc10008) in June 2026&#xA;&#xA;The specification states that the server and the client needs to understand each other, the query that the client will send, the server needs to understand that medium right?&#xA;&#xA;So, in `POST`, `PUT` or `PATCH` we use the `Accept header` from the server to understand that the server can understand a few set of formats like `application/json` or `application/xml` etc.&#xA;&#xA;But think for a moment.&#xA;&#xA;What can happen if we have this&#xA;&#xA;```http&#xA;POST   /posts&#xA;GET    /posts&#xA;GET    /posts/{id}&#xA;PATCH  /posts/{id}&#xA;DELETE /posts/{id}&#xA;QUERY  /posts/&#xA;```&#xA;&#xA;We need to know what methods the api supports right? before sending a `QUERY` request.&#xA;&#xA;That&#39;s when we use `OPTIONS`. The request that sends a header as `Allow: OPTIONS, GET, HEAD, POST` . This means, the API endpoint supports these many request methods. For our case, we need to add the OPTIONS method&#xA;&#xA;```http&#xA;OPTIONS /posts&#xA;POST    /posts&#xA;GET     /posts&#xA;GET     /posts/{id}&#xA;PATCH   /posts/{id}&#xA;DELETE  /posts/{id}&#xA;QUERY   /posts/&#xA;```&#xA;&#xA;So, when we send&#xA;&#xA;```http&#xA;OPTIONS /posts/ HTTP/1.1&#xA;```&#xA;&#xA;The server should send something like this&#xA;&#xA;```http&#xA;HTTP/1.1 204 No Content&#xA;Allow: OPTIONS, GET, HEAD, POST, PUT, PATCH, DELETE, QUERY&#xA;Date: Thu, 22 Jun 2022 11:45:00 GMT&#xA;&#xA;```&#xA;&#xA;From this Header of `ALLOW` we know that `QUERY` is supported on /posts/ endpoint.&#xA;&#xA;We can now procee...&#xA;&#xA;Wait, we need to know what content type is supported still.&#xA;&#xA;Now, we also need&#xA;&#xA;Server sends the Accept in the Response header of the OPTIONS request&#xA;&#xA;There are a few ifs-elses here.&#xA;&#xA;Why?&#xA;&#xA;Let&#39;s see the problem first.&#xA;&#xA;Let&#39;s say you send :&#xA;&#xA;```&#xA;curl -X OPTIONS https://apis.meetgor.com/posts/&#xA;```&#xA;&#xA;This is equivalent of:&#xA;&#xA;```http&#xA;OPTIONS /posts/ HTTP/1.1&#xA;Host: apis.meetgor.com&#xA;```&#xA;&#xA;This means, for the request of /posts/ what headers are given path on a endpoint. This results into something like this:&#xA;&#xA;```http&#xA;HTTP/1.1 200 OK&#xA;Allow: OPTIONS, GET, HEAD, POST, PUT, PATCH, DELETE, QUERY&#xA;Accept: application/json, application/yaml&#xA;&#xA;```&#xA;&#xA;This means, the server accepts json and yaml in the request body.&#xA;&#xA;But but..&#xA;&#xA;There is where we need to make a distinction here.&#xA;&#xA;The `Accept` can be for `POST` `PUT` or `PATCH` too right? How can we distinguish those from `QUERY`. Its likely we support different format for filtering/searching than for creating, listing or updating resources right?&#xA;&#xA;That&#39;s the specification provides the semantics. It specifies `Accept-Query` as the header specifically for the `QUERY` method.&#xA;&#xA;Since query itself has a representation for itself, it needs a accept header to identify what format the server can accept as a query.&#xA;&#xA;So, once that is know, its a matter of time, to send the request body in that format in the `QUERY` method.&#xA;&#xA;```http&#xA;QUERY /posts&#xA;Content-Type: application/json&#xA;&#xA;{&#xA;  &#34;status&#34;: &#34;published&#34;,&#xA;  &#34;type&#34;: &#34;newsletter&#34;&#xA;}&#xA;```&#xA;&#xA;Done.&#xA;&#xA;The query representation is something not a discussion for this post. Its quite taste and usecase specific thing. So we leave it to the developers in making and designing that format.&#xA;&#xA;But the exchange and protocol we follow is this:&#xA;&#xA;-   Check if `QUERY` method is supported with `OPTIONS` method&#xA;-   Also get the `Accept-Query` header to know what the server api supports for representing the query format.&#xA;-   Send the `QUERY` Method with the request body as the supported format for the query and get the response.&#xA;&#xA;Simple.&#xA;&#xA;That&#39;s the basics of HTTP QUERY method.&#xA;&#xA;I will be making a API that supports QUERY method on my apis soon. Will be writing a write up like this for the same. So, stay tuned for that.</content>
      <type>posts</type>
    </item>
  </channel>
</rss>