localhost
GET
Handler - a function that accepts an HTTP request and returns a response.
import { Elysia } from 'elysia'
new Elysia()
// the function `() => 'hello world'` is a handler
.get('/', () => 'hello world')
.listen(3000)A handler may be a literal value, and can be inlined.
import { Elysia, file } from 'elysia'
new Elysia()
.get('/', 'Hello Elysia')
.get('/video', file('kyuukurarin.mp4'))
.listen(3000)Using an inline value always returns the same value which is useful to optimize performance for static resources like files.
This allows Elysia to compile the response ahead of time to optimize performance.
TIP
Providing an inline value is not a cache.
Static resource values, headers and status can be mutated dynamically using lifecycle.
Context contains request information which is unique for each request, and is not shared except for store (global mutable state).
import { Elysia } from 'elysia'
new Elysia()
.get('/', (context) => context.path)
// ^ This is a contextContext can only be retrieved in a route handler. It consists of:
A function to return a custom status code with type narrowing.
import { Elysia } from 'elysia'
new Elysia()
.get('/', ({ status }) => status(418, "Kirifuji Nagisa"))
.listen(3000)GET
It's recommended to use the never-throw approach to return status instead of throwing as it:
set is a mutable property that forms a response accessible via Context.set.
import { Elysia } from 'elysia'
new Elysia()
.get('/', ({ set, status }) => {
set.headers = { 'X-Teapot': 'true' }
return status(418, 'I am a teapot')
})
.listen(3000)Allows us to append or delete response headers represented as an Object.
import { Elysia } from 'elysia'
new Elysia()
.get('/', ({ set }) => {
set.headers['x-powered-by'] = 'Elysia'
return 'a mimir'
})
.listen(3000)TIP
Elysia provides auto-completion for lowercase for case-sensitivity consistency, eg. use set-cookie rather than Set-Cookie.
Redirect a request to another resource.
import { Elysia } from 'elysia'
new Elysia()
.get('/', ({ redirect }) => {
return redirect('https://youtu.be/whpVWVWBW4U?&t=8')
})
.get('/custom-status', ({ redirect }) => {
// You can also set custom status to redirect
return redirect('https://youtu.be/whpVWVWBW4U?&t=8', 302)
})
.listen(3000)When using redirect, returned value is not required and will be ignored. As response will be from another resource.
Set a default status code if not provided.
It's recommended to use this in a plugin that only needs to return a specific status code while allowing the user to return a custom value. For example, HTTP 201/206 or 403/405, etc.
import { Elysia } from 'elysia'
new Elysia()
.onBeforeHandle(({ set }) => {
set.status = 418
return 'Kirifuji Nagisa'
})
.get('/', () => 'hi')
.listen(3000)Unlike the status function, set.status cannot infer the return value type, therefore it can't check if the return value is correctly typed to the response schema.
TIP
HTTP Status indicates the type of response. If the route handler is executed successfully without error, Elysia will return the status code 200.
You can also set a status code using the common name of the status code instead of using a number.
// @errors 2322
import { Elysia } from 'elysia'
new Elysia()
.get('/', ({ set }) => {
set.status
return 'Kirifuji Nagisa'
})
.listen(3000)Elysia provides a mutable store for interacting with cookies.
There's no need for get/set; you can extract the cookie name and retrieve or update its value directly.
import { Elysia } from 'elysia'
new Elysia()
.get('/set', ({ cookie: { name } }) => {
// Get
name.value
// Set
name.value = "New Value"
})See Patterns: Cookie for more information.
Redirect a request to another resource.
import { Elysia } from 'elysia'
new Elysia()
.get('/', ({ redirect }) => {
return redirect('https://youtu.be/whpVWVWBW4U?&t=8')
})
.get('/custom-status', ({ redirect }) => {
// You can also set custom status to redirect
return redirect('https://youtu.be/whpVWVWBW4U?&t=8', 302)
})
.listen(3000)When using redirect, returned value is not required and will be ignored. As response will be from another resource.
We can return a FormData by returning the form utility directly from the handler.
import { Elysia, form, file } from 'elysia'
new Elysia()
.get('/', () => form({
name: 'Tea Party',
images: [file('nagi.web'), file('mika.webp')]
}))
.listen(3000)This pattern is useful if you ever need to return a file or multipart form data.
Or alternatively, you can return a single file by returning file directly without form.
import { Elysia, file } from 'elysia'
new Elysia()
.get('/', file('nagi.web'))
.listen(3000)To return a response streaming out of the box, use a generator function with the yield keyword.
import { Elysia } from 'elysia'
const app = new Elysia()
.get('/ok', function* () {
yield 1
yield 2
yield 3
})In this example, we stream a response by using the yield keyword.
Elysia supports Server Sent Events by providing a sse utility function.
import { Elysia, sse } from 'elysia'
new Elysia()
.get('/sse', function* () {
yield sse('hello world')
yield sse({
event: 'message',
data: {
message: 'This is a message',
timestamp: new Date().toISOString()
},
})
})When a value is wrapped in sse, Elysia will automatically set the response headers to text/event-stream and format the data as an SSE event.
Headers can only be set before the first chunk is yielded.
import { Elysia } from 'elysia'
const app = new Elysia()
.get('/ok', function* ({ set }) {
// This will set headers
set.headers['x-name'] = 'Elysia'
yield 1
yield 2
// This will do nothing
set.headers['x-id'] = '1'
yield 3
})Once the first chunk is yielded, Elysia will send the headers to the client, therefore mutating headers after the first chunk is yielded will do nothing.
If the response is returned without yield, Elysia will automatically convert stream to normal response instead.
import { Elysia } from 'elysia'
const app = new Elysia()
.get('/ok', function* () {
if (Math.random() > 0.5) return 'ok'
yield 1
yield 2
yield 3
})This allows us to conditionally stream a response or return a normal response if necessary.
Before response streaming is completed, if the user cancels the request, Elysia will automatically stop the generator function.
Eden will interpret a stream response as AsyncGenerator allowing us to use for await loop to consume the stream.
import { Elysia } from 'elysia'
import { treaty } from '@elysiajs/eden'
const app = new Elysia()
.get('/ok', function* () {
yield 1
yield 2
yield 3
})
const { data, error } = await treaty(app).ok.get()
if (error) throw error
for await (const chunk of data)
console.log(chunk)Elysia is built on top of Web Standard Request which is shared between multiple runtime like Node, Bun, Deno, Cloudflare Worker, Vercel Edge Function, and more.
import { Elysia } from 'elysia'
new Elysia()
.get('/user-agent', ({ request }) => {
return request.headers.get('user-agent')
})
.listen(3000)This allows access to low-level request information if necessary.
Server instance is a Bun server instance, allowing us to access server information like port number or request IP.
Server will only be available when HTTP server is running with listen.
import { Elysia } from 'elysia'
new Elysia()
.get('/port', ({ server }) => {
return server?.port
})
.listen(3000)We can get request IP by using server.requestIP method
import { Elysia } from 'elysia'
new Elysia()
.get('/ip', ({ server, request }) => {
return server?.requestIP(request)
})
.listen(3000)Elysia provides a minimal Context by default, allowing you to extend the Context for your specific needs using state, decorate, derive, and resolve.
See Extends Context for more information on how to extend a Context.