Skip to content

Latest commit

 

History

History
418 lines (324 loc) · 14.2 KB

File metadata and controls

418 lines (324 loc) · 14.2 KB
id incoming
title HttpIncoming

import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem';

In the request/response life cycle of an HTTP request handled by Podium, different information needs to be accessible at different stages. To cater to this, Podium has an HttpIncoming object which is passed between the different parts of Podium throughout the request/response life cycle.

This HttpIncoming object holds different values during the various stages in a request/response life cycle. The most important values are:

  • The Podium context
  • View properties for use by the document template
  • A URL object for the servers request object (holds query params etc)

HttpIncoming is used in both @podium/layout and @podium/podlet.

The HttpIncoming class is located in the @podium/utils module and when writing an HTTP server without using the supported HTTP framework plugins, it will be necessary to instantiate an instance of this object and pass it between the different parts of Podium.

When using the supported HTTP framework plugins an instance of HttpIncoming is created for you under the hood and passed on as a property on the request between the different parts of the request/response life cycle of the HTTP framework.

import express from 'express';
import Layout from '@podium/layout';

const app = express();

const layout = new Layout({
    name: 'myLayout',
    pathname: '/',
});

const podlet = layout.client.register({
    name: 'myPodlet',
    uri: 'http://localhost:7100/manifest.json',
});

// Set up a document template which take HttpIncoming and a body content.
// This template will be used when .render() is called in a request.
layout.view = (incoming, body) => {
    return `
        <html>
            <head><title>${incoming.view.title}</title></head>
            <body>${body}</body>
        </html>
    `;
};

// Attach the middleware on Express. This will create HttpIncoming under the
// hood plus generate the context and store it on HttpIncoming among other
// things. HttpIncoming will be stored at res.locals.podium
app.use(layout.middleware());

app.get(layout.pathname(), (req, res) => {
    // Get the HttpIncoming object generated by the layout.middleware()
    let incoming = res.locals.podium;

    // Set a view property on HttpIncoming. This can now be used in the
    // document template or anywhere one have access to HttpIncoming.
    incoming.view = {
        title: 'My pretty site'
    };

    // Pass HttpIncoming on to the fetch method. This will pass the generated
    // context on to the request to the podlet.
    const { content } = await podlet.fetch(incoming);

    // Call podiumSend with the content of the podlet. This will now call the
    // document template set on the layout.view property send the response.
    // This will pass on HttpIncoming to the document template under the hood.
    res.podiumSend(content);
});

app.listen(7000);
import FastifyLayout from '@podium/fastify-layout';
import fastify from 'fastify';
import Layout from '@podium/layout';

const app = fastify({ logger: true });

const layout = new Layout({
    name: 'myLayout',
    pathname: '/',
});

const podlet = layout.client.register({
    name: 'myPodlet',
    uri: 'http://localhost:7100/manifest.json',
});

// Set up a document template which take HttpIncoming and a body content.
// This template will be used when .render() is called in a request.
layout.view = (incoming, body) => {
    return `
        <html>
            <head><title>${incoming.view.title}</title></head>
            <body>${body}</body>
        </html>
    `;
};

app.register(FastifyLayout, layout);

app.get(layout.pathname(), async (request, reply) => {
    // Get the HttpIncoming object generated by the pre-hook in the plugin
    const incoming = reply.app.podium;

    // Set a view property on HttpIncoming. This can now be used in the
    // document template or anywhere one have access to HttpIncoming.
    incoming.view = {
        title: 'My pretty site'
    };

    // Pass HttpIncoming on to the fetch method. This will pass the
    // generated context on to the request to the podlet.
    const { content } = await podlet.fetch(incoming);

    // Call podiumSend with the content of the podlet. This will now call
    // the document template set on the layout.view property send the
    // response. This will pass on HttpIncoming to the document template
    // under the hood.
    reply.podiumSend(content);
});

const start = async () => {
    try {
        await app.listen(7000);
        app.log.info(`server listening on ${app.server.address().port}`);
    } catch (err) {
        app.log.error(err);
        process.exit(1);
    }
}
start();
import { HttpIncoming } from '@podium/utils';
import Layout from '@podium/layout';
import http from 'http';

const layout = new Layout({
    name: 'myLayout',
    pathname: '/',
});

const podlet = layout.client.register({
    name: 'myPodlet',
    uri: 'http://localhost:7100/manifest.json',
});

// Set up a document template which take HttpIncoming and a body content.
// This template will be used when .render() is called in a request.
layout.view = (incoming, body) => {
    return `
        <html>
            <head><title>${incoming.view.title}</title></head>
            <body>${body}</body>
        </html>
    `;
};

const server = http.createServer(async (req, res) => {
    // Create a HttpIncoming object
    let incoming = new HttpIncoming(req, res);

    // Set a view property on HttpIncoming. This can now be used in the
    // document template or anywhere one have access to HttpIncoming.
    incoming.view = {
        title: 'My pretty site',
    };

    // Pass HttpIncoming on to the layout processor. This will generate
    // the context and store it on HttpIncoming among other things
    incoming = await layout.process(incoming);

    // Pass HttpIncoming on to the fetch method. This will pass the generated
    // context on to the request to the podlet.
    const { content } = await podlet.fetch(incoming);

    // Pass HttpIncoming and the content of the podlet to the render method.
    // This will now call the document template set on the layout.view property.
    const html = layout.render(incoming, content);

    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/html');
    res.end(html);
});

server.listen(7000);

Constructor

Create a new HttpIncoming instance.

import { HttpIncoming } from '@podium/utils';
const incoming = new HttpIncoming(request, response, params);

options

option type default required details
request http.IncomingMessage null A raw Node.js HTTP request object
response http.ServerResponse null A raw Node.js HTTP response object
params object {} Request scoped parameters
request

A raw Node.js http.IncomingMessage object.

If used with an HTTP framework please note that some frameworks operate with their own "request" objects as a wrapper around http.IncomingMessage. In such cases it is often necessary to gain access to the raw http.IncomingMessage object through a property or method.

response

A raw Node.js http.ServerResponse object.

If used with an HTTP framework please note that some frameworks operate with their own "request" objects as a wrapper around http.IncomingMessage. In such cases it is often necessary to gain access to the raw http.IncomingMessage object through a property or method.

params

An object for passing arbitrary property values for Podium to use.

Note: When using any of the supported HTTP frameworks, params is usually picked up from a special properties object on the request (eg. res.locals in Express.js). Please see the the relevant plugin for the appropriate HTTP framework for further information.

One very common use case for this is to pass a request bound property to a context parser. There are cases where you may want to perform operations on requests prior to running the .middleware() or .process() methods in a layout or podlet and then pass the results of these operations on to a context parser.

The locale context parser does this when setting the request bound locale value:

const app = express();

const layout = new Layout({
    name: 'myLayout',
    pathname: '/',
});

const podlet = layout.client.register({
    name: 'myPodlet',
    uri: 'http://localhost:7100/manifest.json',
});

// Set a locale param to 'nb-NO' on res.locals
app.use((req, res, next) => {
    res.locals = {
        locale: 'nb-NO',
    };
    next();
});

// Attach the middleware on Express. This will create HttpIncoming under the
// hood plus generate the context where the locale param will be picked up from
// res.locals
app.use(layout.middleware());

app.get('/', (req, res) => {
    // Get the HttpIncoming object generated by the layout.middleware()
    let incoming = res.locals.podium;

    // Pass HttpIncoming on to the fetch method. This will pass the generated
    // context where locale now is `nb-NO` on to the request to the podlet.
    const { content } = await podlet.fetch(incoming);

    [ ... snip ...]
});
const app = fastify();

const layout = new Layout({
    name: 'myLayout',
    pathname: '/',
});

const podlet = layout.client.register({
    name: 'myPodlet',
    uri: 'http://localhost:7100/manifest.json',
});

// Register the Fastify Layout Plugin. This will create HttpIncoming under the
// hood plus generate the context where the locale param will be picked up from
// reply.app.params
app.register(FastifyLayout, layout);

// Set a locale param to 'nb-NO' on reply.app.params
app.addHook('onRequest', (request, reply, next) => {
    reply.app.params = {
        locale: 'nb-NO',
    };
    next()
})

app.get(layout.pathname(), async (request, reply) => {
    // Get the HttpIncoming object generated by the pre-hook in the plugin
    const incoming = reply.app.podium;

    // Pass HttpIncoming on to the fetch method. This will pass the
    // generated context on to the request to the podlet.
    const { content } = await podlet.fetch(incoming);

    [ ... snip ...]
});
const layout = new Layout({
    name: 'myLayout',
    pathname: '/',
});

const podlet = layout.client.register({
    name: 'myPodlet',
    uri: 'http://localhost:7100/manifest.json',
});

const server = http.createServer(async (req, res) => {
    // Create a HttpIncoming object and set a locale param to 'nb-NO'
    let incoming = new HttpIncoming(req, res, {
        locale: 'nb-NO',
    });

    // Pass HttpIncoming on to the layout processor. This will generate
    // the context where the local parser will read the locale parameter
    // from HttpIncoming.
    incoming = await layout.process(incoming);

    // Pass HttpIncoming on to the fetch method. This will pass the generated
    // context where locale now is `nb-NO` on to the request to the podlet.
    const { content } = await podlet.fetch(incoming);

    [ ... snip ...]
});

Properties

An HttpIncoming instance has the following properties:

property type getter setter default details
development boolean false Hint regarding whether the podlet / layout are in development mode or not
response http.ServerResponse null A raw Node.js HTTP response object set through the response argument in the constructor
request http.IncomingMessage null A raw Node.js HTTP request object set through the request argument in the constructor
context object {} The context created by the context parser
podlets array null Array of client response objects. Used in @podium/layout.
params object {} Params set through the params argument in the constructor
proxy boolean false Whether the request was handled by the proxy or not
name string '' The name of the podlet / layout
view object {} View parameters for the document template
url URL {} A URL object created out of the original request
css array [] An array of AssetCSS objects
js array [] An array of AssetJS objects

Methods

An HttpIncoming instance has the following methods:

.toJSON()

Returns JSON representation of the HttpIncoming instance.