Options
All
  • Public
  • Public/Protected
  • All
Menu

The API that is provided to route callbacks.

Hierarchy

  • BaseResponseWriter
    • ResponseWriter

Index

Constructors

constructor

  • Parameters

    • req: Request

      The request

    • res: Response

      The response

    • route: Route

      The route

    • context: RequestContext

    Returns ResponseWriter

Properties

request

request: Request

response

response: Response

Protected route

route: Route

Methods

addResponseCookie

  • addResponseCookie(name: string, value: string): void
  • Adds a set-cookie header to the response. This does not replace any cookies with the same name - for that you should use updateResponseCookie.

    Example

     new Router()
       .get('/some/path', ({ addUpstreamResponseCookie, proxy }) => {
         proxy('origin')
         addResponseCookie('my-cookie', 'my-cookie-value')
       })

    Parameters

    • name: string

      Name of the cookie to add.

    • value: string

      Value to set

    Returns void

addUpstreamResponseCookie

  • addUpstreamResponseCookie(name: string, value: string): void
  • Adds a set-cookie header to the response before attempting to cache the response. This does not replace any cookies with the same name - for that you should use updateUpstreamResponseCookie. Furthermore, XDN does not cache responses with set-cookie so if you wish to add a cookie after the response is cached, you should use addResponseCookie.

    Example

     new Router()
       .get('/some/path', ({ addUpstreamResponseCookie, proxy }) => {
         proxy('origin')
         addUpstreamResponseCookie('my-cookie', 'my-cookie-value')
       })

    Parameters

    • name: string

      Name of the cookie to add.

    • value: string

      Value to set

    Returns void

allowCors

  • Sends the necessary response headers to allow CORS

    Parameters

    • Default value config: CorsOptions = {}

      Example

       new Router()
         .match('/api/:path*', ({ allowCors }) => {
           allowCors({
             origin: '*', // this is the default
             methods: ['get', 'post'],
             headers: ['x-some-header'],
             maxAge: 60 * 60, // one hour
             credentials: true
           })
         })

    Returns void

appShell

  • appShell(indexHtmlPath: string): void
  • Serves an HTML app shell from a static file.

    Parameters

    • indexHtmlPath: string

      The path to the app shell html file

      Example

       new Router()
         .fallback(({ appShell }) => {
           appShell('dist/index.html')
         })

    Returns void

cache

  • Sets the caching behavior for both browser and edge.

    Example

     new Router()
       .get('/p/:productId', ({ cache, proxy }) => {
         cache({
           browser: {
             maxAgeSeconds: 0,
             serviceWorkerSeconds: 60 * 60, // 1 hour
           },
           edge: {
             maxAgeSeconds: 60 * 60 * 24 // 24 hours
             staleWhileRevalidateSeconds: 60 * 60 // 1 hour
           }
         })
         proxy('origin')
       })

    The cache() method can be called in the same route where the response is sent, or any prior route. For example, with Next.js, it is common to use the next plugin to automatically inherit page routes based on Next.js conventions, and use the XDN router simply to add caching:

     import { Router } = from '@xdn/core/router'
     import { createNextPlugin } from '@xdn/next'
    
     const { nextMiddleware, renderNext } = createNextPlugin()
    
     new Router()
       .get('/p/:productId', ({ cache, proxy }) => {
         cache({
           browser: {
             maxAgeSeconds: 0,
             serviceWorkerSeconds: 60 * 60, // 1 hour
           },
           edge: {
             maxAgeSeconds: 60 * 60 * 24 // 24 hours
             staleWhileRevalidateSeconds: 60 * 60 // 1 hour
           }
         })
         proxy('origin')
       })
       .use(nextMiddleware)

    Parameters

    Returns void

compute

  • compute(callback: (request: Request, response: Response) => void | Promise<void>): void
  • Execute the provided callback function in the cloud. The callback is passed the request and the response.

    Use this method when you need to compute a response in the cloud rather than at the edge or at build time. A common example is when the response must be computed based on request parameters, headers, or cookies.

    A common example is to look up the destination for a redirect from an external API:

     new Router()
       .get('/products/:id', ({ redirect, compute }) => {
         compute(async (request, response) => {
           const destination = await getDestinationFromAPI(request.params.id)
           redirect(destination)
         })
       })

    This method can be combined with cache to compute responses in the cloud and cache them at edge:

     new Router()
       .get('/products/:id', ({ cache, redirect, compute }) => {
         cache({
           edge: {
             maxAgeSeconds: 60 * 60 * 24,
             staleWhileRevalidateSeconds: 60 * 60,
           }
         })
         compute(async (request, response) => {
           const destination = await getDestinationFromAPI(request.params.id)
           redirect(destination)
         })
       })

    Parameters

    • callback: (request: Request, response: Response) => void | Promise<void>

      A function to run in the cloud to compute the response

    Returns void

proxy

  • Relays the request to the specified backend.

    Example

     new Router()
       .get('/some/path/with/:variable', ({ proxy }) => {
         proxy('legacy', { path: '/some/other/path/with/:variable' })
       })

    In this example, we relay the request to the "legacy" backend. In this case, xdn.config.js must contain a definition for the legacy backend. For example:

     // xdn.config.js
    
     module.exports = {
       backends: {
         legacy: {
           domainOrIp: 'legacy.domain.com',
           hostHeader: 'domain.com'
         }
       }
     }

    Parameters

    • backend: string

      The name of one of the backends in your xdn.config.js file.

    • Optional options: ProxyOptions

    Returns void

    A promise the resolves once the response has been fetched from the upstream site.

redirect

  • redirect(to: string, statusCode?: number): void
  • Redirects the browser to a new location.

    Example

     new Router()
       .get('/p/:productId', ({ redirect }) => {
         return redirect('/products/:productId', 301)
       })

    Parameters

    • to: string

      The URL to which the browser will be redirected.

    • Default value statusCode: number = 302

      The HTTP status to return. Defaults to 301

    Returns void

removeRequestHeader

  • removeRequestHeader(name: string): void
  • Removes a request header.

    Example

     new Router()
       .get('/some/path', async ({ removeRequestHeader, proxy }) => {
         removeRequestHeader('some-header')
         proxy('origin')
       })

    Parameters

    • name: string

      The case-insensitive name of the request header

    Returns void

removeResponseCookie

  • removeResponseCookie(name: string): void
  • Removes a specific set-cookie header from the response. If you wish to remove all such headers use removeHeader.

    Example

     new Router()
       .get('/some/path', ({ removeUpstreamResponseHeader, proxy }) => {
         proxy('origin')
         removeUpstreamResponseCookie('my-cookie')
       })

    Parameters

    • name: string

      The case-insensitive name of the cookie

    Returns void

removeResponseHeader

  • removeResponseHeader(name: string): void
  • Removes a response header immediately before delivering the response downstream.

    Example

     new Router()
       .get('/some/path', ({ removeResponseHeader, proxy }) => {
         proxy('origin')
         removeResponseHeader('some-header')
       })

    Parameters

    • name: string

      The case-insensitive name of the response header

    Returns void

removeUpstreamResponseCookie

  • removeUpstreamResponseCookie(name: string): void
  • Removes a specific set-cookie header from the response before attempting to cache the response. If you wish to remove all such headers use removeUpstreamHeader.

    Example

     new Router()
       .get('/some/path', ({ removeUpstreamResponseHeader, proxy }) => {
         proxy('origin')
         removeUpstreamResponseCookie('my-cookie')
       })

    Parameters

    • name: string

      The case-insensitive name of the cookie

    Returns void

removeUpstreamResponseHeader

  • removeUpstreamResponseHeader(name: string): void
  • Removes a response header before attempting to cache the response. In local development this is same as calling updateUpstreamResponseHeader but on edge it removes a header immediately after the upstream fetch has finished.

    Example

     new Router()
       .get('/some/path', ({ removeUpstreamResponseHeader, proxy }) => {
         proxy('origin')
         removeUpstreamResponseHeader(HTTP_HEADERS.setCookie)
       })

    Parameters

    • name: string

      The case-insensitive name of the response header

    Returns void

render

  • render(cb: (request: Request, proxy: (backend: string, options: ProxyOptions) => void, params: any) => void): void
  • Calls the provided callback to send a response.

    deprecated

    Parameters

    • cb: (request: Request, proxy: (backend: string, options: ProxyOptions) => void, params: any) => void

      Render callback function

        • (request: Request, proxy: (backend: string, options: ProxyOptions) => void, params: any): void
        • Parameters

          Returns void

    Returns void

send

  • send(content: string | (() => string), statusCode?: number, statusMessage?: undefined | string): void
  • Sends content back to client. If content is a string, the respons will be sent directly from the edge. If it is a function, the request will be computed by a JavaScript worker.

    Example

     new Router()
       .get('/some/path', ({ send }) => {
         return send('<html><body>Hello World!</body></html>', 200, 'OK')
       })

    Parameters

    • content: string | (() => string)

      The response body as a string

    • Default value statusCode: number = 200

      The status to send

    • Optional statusMessage: undefined | string

      The status message to send

    Returns void

serveStatic

  • serveStatic(path: string): void
  • Responds with a static asset from the specified path.

    Example

    serveStatic('path/to/asset/from/app/root')

    You can also use variables in the asset path. For example, to return files under the assets directory when the url starts with /static:

     new Router()
       .get('/static/:path*', ({ serveStatic }) => {
         serveStatic('assets/:path*')
       })

    Notes:

    • if a folder contains an 'index.html', that page is also served when requesting the parent folder route. Let's take the example of /posts/1 that will render /posts/1/index.html) They are multiple components involved in this rewrite to make it work with S3 storage:

      1. DeploymentBuilder creates and bundles an assets-aliases.json file, that indicates that '/posts/1' should point to '/posts/1/index.html' asset file.
      2. xdn-subaccount-infra/components/deploy-lambda/src/deploy.js re-uploads '/posts/1/index.html' as '/posts/1' s3 key, which works because S3 is a key based storage and not a filesystem. It's a bit of a hack and takes extra space, but allows root document rendering.
      3. serveStatic(), both in ResponseWriter ad EdgeResponseWriter, remove any trailing slash on path so that both '/posts/1/' and '/posts/1' match the '/posts/1' S3 file
    • We did not use S3 built-in Static Website feature for multiple reasons:

      1. It is http only
      2. /build-slug/public/posts/ renders /build-slug/public/posts/index.html correctly, but /build-slug/public/posts without a trailing slash redirects to /build-slug/public/posts/. While it's easy to rewrite the path and remove trailing slashes, we actually do, it's not easy to add missing trailing slash as we don't know beforehand if the route is a directory or a file. Having a redirect on every route is not acceptable either. The Location header would also need to be rewritten to be relative to the actual website and not the bucket prefix, but that's manageable.

    Parameters

    • path: string

      The relative path to the asset from the app's root directory. You can reference path variables using :variable.

    Returns void

    A promise the resolves once the asset has been fetched from storage.

serviceWorker

  • serviceWorker(path: string): void
  • Returns the service worker with proper edge and browser cache headers

    Parameters

    • path: string

      The path to the service worker relative to the root directory of your app

      Example

       new Router()
         .get('/service-worker.js', ({ serviceWorker }) => {
           serviceWorker('dist/service-worker.js')
         })

    Returns void

setRequestHeader

  • setRequestHeader(name: string, value: string): void
  • Adds or replaces a request header.

    Example

     new Router()
       .get('/some/path', ({ setRequestHeader, proxy }) => {
         setRequestHeader('some-header', 'some-value')
         proxy('origin')
       })

    Parameters

    • name: string

      The case-insensitive name of the request header

    • value: string

      The value to set

    Returns void

setResponseHeader

  • setResponseHeader(name: string, value: string): void
  • Adds or replaces a response header immediately before delivering the response downstream.

    Example

     new Router()
       .get('/some/path', ({ setResponseHeader, proxy }) => {
         proxy('origin')
         setResponseHeader('some-header', 'some-value')
       })

    Parameters

    • name: string

      The case-insensitive name of the response header

    • value: string

      The value to set

    Returns void

setUpstreamResponseHeader

  • setUpstreamResponseHeader(name: string, value: string): void
  • Adds or replaces an upstream response header before attempting to cache the response. In local development this is same as calling setResponseHeader but on edge it adds a header immediately after the upstream fetch has finished.

    Example

     new Router()
       .get('/some/path', ({ setUpstreamResponseHeader, proxy }) => {
         proxy('origin')
         setUpstreamResponseHeader('x-xdn-surrogate-key', 'proxy=origin')
       })

    Parameters

    • name: string

      The case-insensitive name of the response header

    • value: string

      The value to set

    Returns void

updatePath

  • updatePath(destination: string): void
  • Rewrites the request path.

    Example:

     router.get('/products/:id', ({ updatePath }) => {
       updatePath('/p/:id')
     })

    Parameters

    • destination: string

      a new route path, which can include params captured from the original path

    Returns void

updateRequestHeader

  • updateRequestHeader(name: string, match: RegExp, replace: string): void
  • Alters a request header. Use this method to derive the new header value from the existing one.

    Example

     new Router()
       .get('/some/path', ({ updateRequestHeader, proxy }) => {
         updateRequestHeader('some-header', /some-.*-part/gi, 'some-replacement')
         proxy('origin')
       })

    Parameters

    • name: string

      The case-insensitive name of the request header

    • match: RegExp

      Regex to find the part that should be replaced.

    • replace: string

      Value that will replace the matched part.

    Returns void

updateResponseCookie

  • updateResponseCookie(name: string, match: RegExp, replace: string): void
  • Updates a set-cookie header in the response. If there are multiple cookies with the same name, all of them will be updated.

    Example

     new Router()
       .get('/some/path', ({ updateUpstreamResponseCookie, proxy }) => {
         proxy('origin')
         updateUpstreamResponseCookie('my-cookie', /Domain=.+;/, 'Domain=mydomain.com;')
       })

    Parameters

    • name: string

      Case-insensitive name of the cookie to update

    • match: RegExp

      Regex to find the part that should be replaced.

    • replace: string

      Value that will replace the matched part.

    Returns void

updateResponseHeader

  • updateResponseHeader(name: string, match: RegExp, replace: string): void
  • Alters a response header immediately before delivering the response downstream. Use this method to derive the new header value from the existing one.

    Example

     new Router()
       .get('/some/path', ({ updateResponseHeader, proxy }) => {
         proxy('origin')
         updateResponseHeader('some-header', /some-.*-part/gi, 'some-replacement')
       })

    Parameters

    • name: string

      The case-insensitive name of the response header

    • match: RegExp

      Regex to find the part that should be replaced.

    • replace: string

      Value that will replace the matched part.

    Returns void

updateUpstreamResponseCookie

  • updateUpstreamResponseCookie(name: string, match: RegExp, replace: string): void
  • Updates a set-cookie header in the response before attempting to cache the response. If there are multiple cookies with the same name, all of them will be updated.

    Example

     new Router()
       .get('/some/path', ({ updateUpstreamResponseCookie, proxy }) => {
         proxy('origin')
         updateUpstreamResponseCookie('my-cookie', /Domain=.+;/, 'Domain=mydomain.com;')
       })

    Parameters

    • name: string

      Case-insensitive name of the cookie to update

    • match: RegExp

      Regex to find the part that should be replaced.

    • replace: string

      Value that will replace the matched part.

    Returns void

updateUpstreamResponseHeader

  • updateUpstreamResponseHeader(name: string, match: RegExp, replace: string): void
  • Alters an upstream response header before attempting to cache the response. Use this method to derive the new header value from the existing one. In local development this is same as calling updateResponseHeader but on edge it updates a header immediately after the upstream fetch has finished.

    Example

     new Router()
       .get('/some/path', ({ updateUpstreamResponseHeader, proxy }) => {
         proxy('origin')
         updateUpstreamResponseHeader('cache-control', /public/gi, 'private')
       })

    Parameters

    • name: string

      The case-insensitive name of the response header

    • match: RegExp

      Regex to find the part that should be replaced.

    • replace: string

      Value that will replace the matched part.

    Returns void

Generated using TypeDoc