Responses

When Curi receives a location, it compares the location's pathname to each route's path to find which one matches best and uses that route to create a response object.

The Properties of a Response Object

There are two types of response properties.

The "match" properties are set based on the route that matches a location. A response always has these properties.

// match properties
{
  // The location object used to generate the response.
  location: { pathname: '/photos/6789/12345', ... },

  // The name of the best matching route
  name: 'Photo',

  // The name of ancestor routes that matched
  // part of the location's pathname
  partials: ['Album'],

  // An object containing the values parsed
  // from the pathname by path-to-regexp.
  // This includes params from ancestor routes.
  params: { photoID: 12345, albumID: 6789 },
}

The "settable" properties are ones that are added by a matched route's respond function. These only exist on the response when they are returned by a route's respond function.

The "settable" properties are:

body

The component(s) that should be rendered for a route.

meta

An object with metadata for a response.

data

A place to attach any data you want to the response, such as data loaded in the route's resolve function.

redirect

An object describing a route that Curi should automatically redirect to.

// settable properties (optional)
{
  body: Photo,
  // or maybe
  body: {
    menu: PhotoMenu,
    main: Photo
  },
  // Please see below for more information
  // about this property

  meta: {
    status: 200,
    title: 'Photo 12345'
  },

  data: {...},

  redirect: {...}
}

Response Body

Curi isn't strict about how you use responses, but you will most likely always want to use a route's respond function to attach a body property to a response. The usual pattern is to use a route's body property to describe which component(s) to render when a route matches. This can either be a single component for basic layouts or an object with a number of components for advanced layouts.

// do NOT do this
// mixing body shapes complicates rendering
let routes = prepareRoutes([
  {
    respond() {
      return { body: One }
    }
  },
  {
    respond() {
      return {
        body: {
          main: Main,
          menu: Menu
        }
      }
    }
  }
]);

Redirect Response

When a route's respond function returns an object with a redirect property, the router will use it to generate a location object that Curi will automatically redirect to.

{
  // The redirect property provides information on
  // where you should redirect to
  redirect: { name: "Login" }
}

When creating a router, you can set the invisibleRedirects option to true and the response will not be sent to observers and one time functions. Instead, the response for the location that is redirected to will be the next emitted response. In either case, the router will automatically redirect to the route specified by response.redirect.

let router = createRouter(browser, routes, {
  invisibleRedirects: true
});

This property can also be used to specify an external redirect (a redirect to a location that is not within the application). This is done by setting an externalURL property on the redirect object. It is up to the application to redirect to the external location. Responses with an external redirect will be emitted when invisibleRedirects is true.

// a route with an external redirect
{
  respond() {
    return {
      redirect: {
        externalURL: "https://example.com"
      }
    };
  }
}

// a route observe can detect and automatically redirect
router.observe(({ response }) => {
  if (response.redirect && response.redirect.externalURL) {
    window.location.replace(response.redirect.externalURL);
  }
})