Render different HTML based on HTTP method in Astro

By

Learn how to render completely different HTML in an Astro page depending on the HTTP method by checking Astro.request.method for POST, GET, or DELETE.

~~~

To render different HTML based on the HTTP method in Astro, check Astro.request.method in the template and render conditionally.

I had the need to render completely different HTML depending on the HTTP method used to reach an Astro page.

I used this technique:

---
//... some server side logic
---

{Astro.request.method === 'POST' && 
  <div>
    //...
  </div>
}

{Astro.request.method === 'DELETE' && 
  <div>
    //...
  </div>
}

{Astro.request.method === 'GET' && 
  <div>
    //...
  </div>
}

Astro.request is a standard Request object, the same one you’d get in a service worker or a Cloudflare Worker. Its method property is a string like 'GET' or 'POST', always uppercase.

Each {condition && <element>} block works like in JSX. When the condition is true, the element renders. When it’s false, nothing renders.

When is this useful?

The classic case is a form that posts back to the same page.

The first visit is a GET, so you render the form. When the user submits, the browser sends a POST to the same URL, and you render a confirmation instead:

---
let submitted = false

if (Astro.request.method === 'POST') {
  const data = await Astro.request.formData()
  const email = data.get('email')
  //save the email somewhere
  submitted = true
}
---

{submitted && <p>Thanks, you're on the list!</p>}

{!submitted && (
  <form method="POST">
    <input type="email" name="email" required />
    <button>Subscribe</button>
  </form>
)}

The whole flow lives in one file. No separate API endpoint, no client-side JavaScript.

The page must be server-rendered

This is the pitfall that trips people up.

A static Astro page is built once, at build time, and the check runs during that build. The generated HTML is then served for every request, no matter the method. Worse, a static host has no way to accept a POST to an HTML file, so form submissions fail.

The fix is to render the page on demand. Add an adapter to your project and opt the page out of prerendering:

---
export const prerender = false
---

Or set output: 'server' in your Astro config if most of your site works this way.

Once the page runs on the server for each request, Astro.request.method reflects the real method the browser used, and the conditional rendering works as expected.

Tagged: Astro · All topics
~~~

Related posts about astro: