Skip to main content
Version: 2.x

Add custom endpoints to your server

The main entry points of a Front-Commerce application are frontend URLs displaying your actual website and the GraphQL schema. But in some specific cases, you may want to extend your Node.js server with additional endpoints.

For instance, this can be the case when you send a link within an email to one of your customers. If an action should be triggered when the user clicks on it, you don't want to add failure opportunities by displaying a webpage which will then trigger a GraphQL mutation. You want to trigger the action directly, and then redirect the user to an actual page.

This can also be useful if you want to add new pages that are used in an administration interface. For instance, you may want to provide an iframe that will let you preview how your WYSIWYG component will be displayed in Front-Commerce. This is what we are going to explain in this documentation.

Technically, Front-Commerce’s server is based on Express. To add your custom route which will add your custom endpoint, you need to register it from your own module.

What is a module?

A module is declared using the modules entry from the .front-commerce.js file. Each module can contain client code (See Extend the theme), and server code (current guide).

Once the module is declared, Front-Commerce will automatically add your custom server entrypoints following your module configuration in my-module/server/module.config.js.

Important

GraphQL modules, are modules related to the server, but they won't let you extend anything else but your GraphQL Schema. See Extend the GraphQL Schema for more information.

Register additional routes

In the case of the WYSIWYG preview, let's say that when a user visits the wysiwyg-preview URL, we want to display static files that will let anyone preview how an html string will be transformed by Front-Commerce's Wysiwyg component.

To do so, we need to create our server config file, and configure its entrypoint key.

my-module/server/module.config.js
import router from "./express";

export default {
endpoint: {
// The path added to your Front-Commerce server
path: "/wysiwyg-preview",
// The router used for this path
router: router,
},
};

If we translated this in a standard express application, it would look like this:

import router from "./express";

app.use("/wysiwyg-preview", router());
note

See our express middleware to understand how the magic works: withCustomRouters.

Thus, the my-module/server/express.js file within your module should be a function returning either a standard express route ((req, res, next) => { /* ... */ }) or an express router.

Now, if we want to display our WYSIWYG preview iframe, it could look like this:

my-module/server/express/index.js
import path from "path";
import cors from "cors";
import express, { Router } from "express";
import config from "config/website";

const ONE_HOUR = 60 * 60;

export default () => {
const router = new Router();

// We make sure that the resources are only available for
// our administration interface
router.use(
cors({
origin: config.admin,
})
);

// And then, we render a static page that let's you
// preview some wysiwyg content
router.use(
express.static(path.join(process.cwd(), "build/wysiwyg"), {
setHeaders: function (res, url, stat) {
res.setHeader("Cache-Control", `public, max-age=${ONE_HOUR}`);
},
})
);

return router;
};

Add a global server middleware

We've added our middleware that is now available under the /wysiwyg-preview path. But what if we want to add a middleware that should be used before any requests to your application?

To do so, you will need to add the option __dangerouslyOverrideBasePathChecks to your endpoint configuration.

my-module/server/module.config.js
import router from "./express";

export default {
endpoint: {
__dangerouslyOverrideBasePathChecks: true,
path: "/",
router: router,
},
};

Indeed, if you don't set this key to true, Front-Commerce will check that you don't setup an invalid path.

For instance, if your application is a migration from an older website, you might want to intercept all your requests to redirect old URLs to new ones. In express, you can do this by creating a middleware. But this means that all the URLs need to pass by this middleware. This is what __dangerouslyOverrideBasePathChecks stands for: it lets you define the path you want (/ in this case) even if it seems dangerous. Once it is set, the middleware can add the redirects for the relevant URLs.

Subdirectory based urls and global middleware

If your store URLs are /fr and /en, you may want to add a root middleware that would for instance handle /.well-known urls.

Using endpoint.__dangerouslyOverrideBasePathChecks as illustrated in the previous section would still mount the returned router under each sub-directory (/fr/.well-known and /en/.well-known).

In this case, you must use the rootEndpoint key. It has the exact same signature than endpoint but will mount the returned router at the global level.

my-module/server/module.config.js
import router from "./express";

export default {
rootEndpoint: {
__dangerouslyOverrideBasePathChecks: true,
path: "/",
router: router,
},
};

Extend the HTTP server with onServerInit

Since version 2.30

The onServerInit hook is allows you to extend the Express HTTP server or perform additional tasks during server initialization.

To use the onServerInit hook, follow the steps detailed below.

First, create a new server module or edit an existing module.config.js file.

In this file, define the onServerInit function. This function will be called when the server is initialized and will receive an instance of the current server object as a parameter.

my-module/server/module.config.js
export default {
onServerInit: (server) => {
// Perform server initialization tasks here
console.log("Server is initialized");
},
};

Finally, restart your server. You should now see a "Server is initialized" console log once your server has started.

You're now ready to extend your server with any custom logic you need.

tip

We have created a working example of a server module that uses the onServerInit hook to add a WebSocket server to the Express server. You can find the example in the Front-Commerce examples repository.

You can browse it's code and run it locally to see how the onServerInit hook works.