/ Load Balancing

One Hostname, Multiple Apps, and Paths

In a perfect world, a service like Fly would perform magic. We could offer our services and claim that everything will work seamlessly - you won't need to make alterations to your applications! That isn't true, yet. In order to take advantage of some of the best features that Fly has to offer, like the flexible routing rules for global load balancing, you'll need to have a solid understanding of relative and absolute paths and how they apply within your code.

It's All Relative... Unless It's Absolute

To begin, let's determine what paths are and the different forms they can take. In HTML, there are two kinds of paths:

  • Absolute Paths.
  • Relative Paths.

Paths are relevant when you're linking somewhere, like so...

Relative:

<a href="radical-page.html">Check out this radical page!</a>

Absolute:

<a href="https://othersite.com/blog/cool-page.html">Check out our friend's cool page!</a>

Or, when assets are involved...

Relative:

<link href='assets/application.css' rel='stylesheet'>

Absolute:

<link href='/assets/application.css' rel='stylesheet'>

Absolute pathing occurs when...

  • You're linking to a site that's different than your own. You must include the entire web address. In our example case, that's all of: https://example.com/blog/cool-page.html; it's the absolute location of the resource.

  • You're inter-linking within your own HTML pages and you want a specific, absolute location instead of a relative one. For example: /path/to/thing/cool-page.html. This will become clearer when we see relative paths in motion.

Before venturing forth: It's important to understand that the "root domain" refers to /; / is short-hand for the root domain, that is: example.com/.

Relative paths can be tricky...

Let's say you're surfing: https://example.com/blog/radical-page.html. Within radical-page.html, there's a link to another page: relaxing-page.html. The link looks like this, within the code:

<a href="relaxing-page.html">Check out this relaxing page!</a>

Clicking the link will take you to: /blog/relaxing-page.html. No other path is specified, so your browser will interpret relaxing-page.html as being under the same parent directory as radical-page.html; that's how it knew to serve it from /blog/ instead of trying example.com/relaxing-page.html.

There's a few ways one can apply a relative path:

  • Relative to its parent folder: relaxing-page.html.
  • Back one directory: ../relaxing-page.html.
  • Back two directories: ../../relaxing-page.html.

Note how there is no leading /. A leading / indicates absolute-ness.

Now, how to apply an absolute path:

  • From a specific location: /a/specific/subfolder/relaxing-page.html.
  • Absolute from root: /relaxing-page.html.

Understanding how paths work is vital when configuring your application to play well with your proxies, delivery networks, or load balancers. It's crucial, too, when using Fly's routing rules.

Relatively Fly

Fly enables you to mount various backends on differing subfolders. When setting up a backend, you can choose a Path to Match. This path is the subfolder that you'll mount your backend on.

Routing page sample

You could...

  • Put a Ghost Blog on /blog/.
  • Use GitHub Pages for /docs/.
  • Use Squarespacee for /store/.

... Or any other combination that you can dream up.

Optionally, you can specify the Rewrite Path.

The Path to Match is useful because it enables you to mount everything onto a single domain using subfolders. The Rewrite Path is important because it tells your backend what the new root domain is. Without it, your backend would not be able to find its assets.

For example...

Let's consider that you have a Heroku application that's hosted on: https://example.herokuapp.com. You add your application to Fly, wanting to make it available as a subfolder - /dashboard/ - on your own custom HTTPS domain, like: https://exampleapp.com/dashboard/.

If you simply change the Path to Match...

Any requests to https://exampleapp.com/dashboard/ will be routed to https://example.herokuapp.com/dashboard.

Without you telling it so, your application is not aware that its assets are now expected from /dashboard/ instead of the root domain: /. Your site may appear broken.

The Rewrite Path gives you the option to direct the Path to Match to a different path on the backend. If we want the matching path to be /dashboard and the Rewrite Path to be /controls/, we will redirect requests like so:

Any requests to https://example.com/dashboard/ will be routed to https://example.herokuapp.com/controls/.

Once configured, you must now alter your asset paths within your code to be aware that /dashboard/ is your new root domain. Depending on how you're setting up your application, there's different ways to do this.

Choose Your Path

HTML - Base Tag

You can alter the paths within the HTML manually; your assets could be set absolutely, considering /dashboard/ as the new root domain instead of /. Or, you can use the <base> tag.

A <base> tag is included within the <head> of your HTML. Using it, you can define the target URL for relatives URLs within the document. For example, if your head includes:

<head>
  <base href="https://example.com/assets/" target="_blank">
</head>

Other assets will know to apply relative to https://example.com/assets:

<link href='application.css' rel='stylesheet'>

Read more here.

JavaScript (Express)

If you're using express, you can use the express.static built-in middleware. You can set-up a virtual path prefix, like so:

app.use('/dashboard', express.static('public'))

This allows the files you have stored within your public directory to be accessible from /dashboard.

Read more here.

JavaScript (Angular)

Within Angular, you can specify the site_prefix variable:

angular.module('app').config(function ($routeProvider) {
  var site_prefix = '/dashboard';
  $routeProvider.
  when(site_prefix + '/', {
    controller: UsersCtrl,
    templateUrl: 'partials/users.html'
  }).
});

More here.

JavaScript (React)

The Router is where the prefixing magic happens:

<Router>
    <Route component={Main} path="dashboard">
        <Route path="/" component={Home}/>
        <Route path="/users" component={User}/>
    </Route>
</Router>

This will append /dashboard before the other Route paths.

Docs here.

Rails

Within Rails, this functionality is baked into the default configuration. You can set the RAILS_RELATIVE_URL_ROOT environment variable to tell your application what the the prefix is. For our example case, it'd be RAILS_RELATIVE_URL_ROOT= "/dashboard".

Read more here.

Laravel (PHP)

Within routes/web.php, you can supply your prefix:

Route::prefix('dashboard')->group(function () {
    Route::get('users', function () {
        // Matches The "/dashboard/users" URL
    });
});

For more information, give the documentation a read.

It Gets Better

Paths are confusing at first. Fly makes routing and load balancing significantly easier than manually configuring and managing your own. Once you're comfortable with the basics of relative vs. absolute paths, you'll be able to use Fly routing rules to assemble the tidiest infrastructure you can envision... All from One Hostname to Rule Them All!

Fly is free to signup, and so are your first 2,000,000 requests and 100GB of transfer every month.

Kellen Evan Person

@thegoodroot

Kellen Evan Person

A polite, forest-dwelling Canadian who enjoys coding and writing. He's spent near two decades building web applications and strives to keep development fun and light-hearted.

North Vancouver, Canada