Skip to content

ctx.req.url

Parsed URL object of the incoming request.

bash
curl 'https://example.com/users?id=1'
js
app.use((ctx) => {
  console.log(ctx.req.url)
  /*
  URL {
    href: 'https://example.com/users?id=1',
    origin: 'https://example.com',
    protocol: 'https:',
    username: '',
    password: '',
    host: 'example.com',
    hostname: 'example.com',
    port: '',
    pathname: '/users',
    search: '?id=1',
    searchParams: URLSearchParams { 'id' => '1' },
    hash: ''
  }
   */
})

ctx.req.url=

Overwrite the request URL using a string or URL instance.

js
app.use((ctx) => {
  ctx.req.url = 'https://example.com/users?id=2'
  // or
  ctx.req.url = new URL('https://example.com/users?id=2')
})

ctx.req.href

Full request URL string including protocol, host, path, query, and hash.

bash
curl 'https://example.com/users?page=1'
js
app.use((ctx) => {
  console.log(ctx.req.href) // -> "https://example.com/users?page=1"
})

ctx.req.href=

Replace the full request URL string.

bash
curl 'https://example.com/users?page=1'
js
app.use((ctx) => {
  ctx.req.href = 'https://example.com/users?page=2'
})

ctx.req.origin

Origin portion of the URL (scheme + host + port).

bash
curl 'https://example.com:8080/dashboard'
js
app.use((ctx) => {
  console.log(ctx.req.origin) // -> "https://example.com:8080"
})

ctx.req.origin=

Replace the origin while keeping path, search, and hash components.

js
app.use((ctx) => {
  ctx.req.origin = 'https://www.example.com'
})

ctx.req.protocol

URL protocol including the trailing colon.

bash
curl 'http://example.com/'
js
app.use((ctx) => {
  console.log(ctx.req.protocol) // -> "http:"
})

ctx.req.protocol=

Set the request protocol.

js
app.use((ctx) => {
  ctx.req.protocol = 'https:'
})

ctx.req.host

Host with port (if present).

bash
curl 'https://example.com:8080/dashboard'
js
app.use((ctx) => {
  console.log(ctx.req.host) // -> "example.com:8080"
})

ctx.req.host=

Set the host string (optionally including port).

js
app.use((ctx) => {
  ctx.req.host = 'www.example.com'
})

ctx.req.hostname

Hostname without port.

bash
curl 'https://example.com:8080/dashboard'
js
app.use((ctx) => {
  console.log(ctx.req.hostname) // -> "example.com"
})

ctx.req.hostname=

Set the hostname.

js
app.use((ctx) => {
  ctx.req.hostname = 'www.example.com'
})

ctx.req.port

Port string, or empty string for the default port.

bash
curl 'https://example.com:8080/dashboard'
js
app.use((ctx) => {
  console.log(ctx.req.port) // -> "8080"
})

ctx.req.port=

Set the port string.

js
app.use((ctx) => {
  ctx.req.port = '8080'
})

ctx.req.pathname

URL pathname starting with /.

bash
curl 'https://example.com/dashboard'
js
app.use((ctx) => {
  console.log(ctx.req.pathname) // -> "/dashboard"
})

ctx.req.pathname=

Set the pathname.

js
app.use((ctx) => {
  ctx.req.pathname = '/dashboard'
})

Raw search string including ?, or empty string when absent.

bash
curl 'https://example.com/users?page=1'
js
app.use((ctx) => {
  console.log(ctx.req.search) // -> "?page=1"
})

ctx.req.search=

Set the raw search string (leading ? optional).

js
app.use((ctx) => {
  ctx.req.search = 'page=42'
})

ctx.req.hash

Hash fragment including #.

js
app.use((ctx) => {
  console.log(ctx.req.hash) // -> ""
})

ctx.req.hash=

Set the hash fragment.

js
app.use((ctx) => {
  ctx.req.hash = '#hash'
})

ctx.req.method

HTTP method associated with the request.

bash
curl --request GET 'https://example.com'
js
app.use((ctx) => {
  console.log(ctx.req.method) // -> "GET"
})

ctx.req.method=

Override the request method.

js
app.use((ctx) => {
  ctx.req.method = 'POST'
})

ctx.req.query

Parsed query object (duplicate keys become arrays).

bash
curl 'https://example.com/search?q=hoa&page=1&page=2'
js
app.use((ctx) => {
  console.log(ctx.req.query) // -> { q: 'hoa', page: ['1',  '2'] }
})

ctx.req.query=

Replace query parameters with a plain object.

js
app.use((ctx) => {
  ctx.req.query = { search: 'hoa', page: ['3', '4'] }
})

ctx.req.headers

Plain object snapshot of request headers.

bash
curl 'https://example.com/' \
  -H 'X-Foo: foo' \
  -H 'X-Bar: bar'
js
app.use((ctx) => {
  console.log(ctx.req.headers) // -> { 'x-foo': 'foo', 'x-bar': 'bar' }
})

ctx.req.headers=

Replace request headers with a Headers object, plain object, or array of entries.

js
app.use((ctx) => {
  ctx.req.headers = {
    'X-Foo': 'foo',
    'X-Bar': 'bar'
  }
  // or
  ctx.req.headers = new Headers([
    ['X-Foo', 'foo'],
    ['X-Bar', 'bar']
  ])
  // or
  ctx.req.headers = [
    ['X-Foo', 'foo'],
    ['X-Bar', 'bar']
  ]
})

ctx.req.body

Underlying ReadableStream body.

js
app.use((ctx) => {
  console.log(ctx.req.body) // -> ReadableStream | null
})

ctx.req.body=

Replace the underlying request body with any value.

js
app.use((ctx) => {
  ctx.req.body = {
    name: 'Hoa'
  }
  // or
  const encoder = new TextEncoder()
  ctx.req.body = new ReadableStream({
    start (controller) {
      controller.enqueue(encoder.encode('patched body'))
      controller.close()
    }
  })
})

ctx.req.get(field)

Retrieve a request header by name (case-insensitive).

bash
curl 'https://example.com/' \
  -H 'X-Foo: foo' \
  -H 'Referrer: google.com'
js
app.use((ctx) => {
  console.log(ctx.req.get('x-foo')) // -> "foo"
  console.log(ctx.req.get('referer')) // -> "google.com"
  console.log(ctx.req.get('referrer')) // -> "google.com"
})

ctx.req.getSetCookie()

Return all Set-Cookie header values as an array.

bash
curl 'https://example.com/' \
  -H 'Set-Cookie: session=abc' \
  -H 'Set-Cookie: theme=dark'
js
app.use((ctx) => {
  console.log(ctx.req.getSetCookie()) // -> ["session=abc","theme=dark"]
})

ctx.req.has(field)

Check if a request header is present.

bash
curl 'https://example.com/' \
  -H 'X-Foo: foo'
js
app.use((ctx) => {
  console.log(ctx.req.has('x-foo')) // -> true
  console.log(ctx.req.has('x-bar')) // -> false
})

ctx.req.set(field, value)

Set a single header value.

js
app.use((ctx) => {
  ctx.req.set('X-Bar', 'bar')
})

ctx.req.set(headers)

Set multiple headers from a plain object.

js
app.use((ctx) => {
  ctx.req.set({
    'X-Foo': 'foo',
    'X-Bar': 'bar'
  })
})

ctx.req.append(field, value)

Append a header value without replacing existing ones.

js
app.use((ctx) => {
  ctx.req.append('X-Foo', 'foo')
  ctx.req.append('X-Bar', 'bar')
})

ctx.req.append(headers)

Append multiple header values from a plain object.

js
app.use((ctx) => {
  ctx.req.append({
    'X-Foo': 'foo',
    'X-Bar': 'bar'
  })
})

ctx.req.delete(field)

Delete a request header.

js
app.use((ctx) => {
  ctx.req.delete('cookie')
})

ctx.req.ips

Array of IP addresses from the X-Forwarded-For header.

bash
curl 'https://example.com/' \
  -H 'X-Forwarded-For: 203.0.113.1, 198.51.100.2'
js
app.use((ctx) => {
  console.log(ctx.req.ips) // -> ["203.0.113.1","198.51.100.2"]
})

ctx.req.ip

Best-effort client IP address from standard headers. Checks headers in the following order:

  • x-client-ip
  • x-forwarded-for
  • cf-connecting-ip
  • do-connecting-ip
  • fastly-client-ip
  • true-client-ip
  • x-real-ip
  • x-cluster-client-ip
  • x-forwarded
  • forwarded-for
  • forwarded
  • x-appengine-user-ip
  • cf-pseudo-ipv4
bash
curl 'https://example.com/' \
  -H 'X-Client-IP: 203.0.113.1' \
  -H 'X-Forwarded-For: 203.0.113.2, 198.51.100.2'
js
app.use((ctx) => {
  console.log(ctx.req.ip) // -> "203.0.113.1"
})

ctx.req.length

Content length in bytes, or null if unavailable.

bash
curl --request POST 'https://example.com/' \
  -H 'Content-Type: text/plain; charset=utf-8' \
  --data 'Hello, Hoa!'
js
app.use((ctx) => {
  console.log(ctx.req.length) // -> 11
})

ctx.req.type

Content type without parameters (e.g., application/json).

bash
curl 'https://example.com/' \
  -H 'Content-Type: application/json; charset=utf-8'
js
app.use((ctx) => {
  console.log(ctx.req.type) // -> "application/json"
})

ctx.req.blob()

Read the request body as a Blob.

bash
curl --request POST 'https://example.com/' \
  -H 'Content-Type: text/plain; charset=utf-8' \
  --data 'Hello, Hoa!'
js
app.use(async (ctx) => {
  const blob = await ctx.req.blob()
  console.log(await blob.text()) // -> "Hello, Hoa!"
})

Note: Body reader helpers such as ctx.req.blob(), ctx.req.arrayBuffer(), ctx.req.text(), ctx.req.json(), and ctx.req.formData() can each be invoked only once per request because they consume the underlying stream.

ctx.req.arrayBuffer()

Read the request body as an ArrayBuffer.

bash
curl --request POST 'https://example.com/' \
  -H 'Content-Type: text/plain; charset=utf-8' \
  --data 'Hello, Hoa!'
js
app.use(async (ctx) => {
  const buffer = await ctx.req.arrayBuffer()
  console.log(new TextDecoder().decode(buffer)) // -> "Hello, Hoa!"
})

ctx.req.text()

Read the request body as text.

bash
curl --request POST 'https://example.com/' \
  -H 'Content-Type: text/plain; charset=utf-8' \
  --data 'Hello, Hoa!'
js
app.use(async (ctx) => {
  const text = await ctx.req.text()
  console.log(text) // -> "Hello, Hoa!"
})

ctx.req.json()

Read the request body as parsed JSON.

bash
curl --request POST 'https://example.com/' \
  -H 'Content-Type: application/json; charset=utf-8' \
  --data '{"name": "Hoa"}'
js
app.use(async (ctx) => {
  const body = await ctx.req.json()
  console.log(body) // -> { name: 'Hoa' }
})

ctx.req.formData()

Read the request body as FormData.

bash
curl --request POST 'https://example.com/' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data 'name=Hoa'
js
app.use(async (ctx) => {
  const form = await ctx.req.formData()
  console.log(form.get('name')) // -> "Hoa"
})

ctx.req.toJSON()

Return JSON representation of the request.

js
app.use((ctx) => {
  console.log(ctx.req.toJSON()) // -> { method, url, headers }
})