1 | <h1 align="center">connect-history-api-fallback</h1>
|
---|
2 | <p align="center">Middleware to proxy requests through a specified index page, useful for Single Page Applications that utilise the HTML5 History API.</p>
|
---|
3 |
|
---|
4 | [![Build Status](https://travis-ci.org/bripkens/connect-history-api-fallback.svg?branch=master)](https://travis-ci.org/bripkens/connect-history-api-fallback)
|
---|
5 | [![Dependency Status](https://david-dm.org/bripkens/connect-history-api-fallback/master.svg)](https://david-dm.org/bripkens/connect-history-api-fallback/master)
|
---|
6 |
|
---|
7 | [![NPM](https://nodei.co/npm/connect-history-api-fallback.png?downloads=true&downloadRank=true)](https://nodei.co/npm/connect-history-api-fallback/)
|
---|
8 |
|
---|
9 |
|
---|
10 | <h2>Table of Contents</h2>
|
---|
11 |
|
---|
12 | <!-- TOC depthFrom:2 depthTo:6 withLinks:1 updateOnSave:1 orderedList:0 -->
|
---|
13 |
|
---|
14 | - [Introduction](#introduction)
|
---|
15 | - [Usage](#usage)
|
---|
16 | - [Options](#options)
|
---|
17 | - [index](#index)
|
---|
18 | - [rewrites](#rewrites)
|
---|
19 | - [verbose](#verbose)
|
---|
20 | - [htmlAcceptHeaders](#htmlacceptheaders)
|
---|
21 | - [disableDotRule](#disabledotrule)
|
---|
22 |
|
---|
23 | <!-- /TOC -->
|
---|
24 |
|
---|
25 | ## Introduction
|
---|
26 |
|
---|
27 | Single Page Applications (SPA) typically only utilise one index file that is
|
---|
28 | accessible by web browsers: usually `index.html`. Navigation in the application
|
---|
29 | is then commonly handled using JavaScript with the help of the
|
---|
30 | [HTML5 History API](http://www.w3.org/html/wg/drafts/html/master/single-page.html#the-history-interface).
|
---|
31 | This results in issues when the user hits the refresh button or is directly
|
---|
32 | accessing a page other than the landing page, e.g. `/help` or `/help/online`
|
---|
33 | as the web server bypasses the index file to locate the file at this location.
|
---|
34 | As your application is a SPA, the web server will fail trying to retrieve the file and return a *404 - Not Found*
|
---|
35 | message to the user.
|
---|
36 |
|
---|
37 | This tiny middleware addresses some of the issues. Specifically, it will change
|
---|
38 | the requested location to the index you specify (default being `/index.html`)
|
---|
39 | whenever there is a request which fulfills the following criteria:
|
---|
40 |
|
---|
41 | 1. The request is a GET request
|
---|
42 | 2. which accepts `text/html`,
|
---|
43 | 3. is not a direct file request, i.e. the requested path does not contain a
|
---|
44 | `.` (DOT) character and
|
---|
45 | 4. does not match a pattern provided in options.rewrites (see options below)
|
---|
46 |
|
---|
47 | ## Usage
|
---|
48 |
|
---|
49 | The middleware is available through NPM and can easily be added.
|
---|
50 |
|
---|
51 | ```
|
---|
52 | npm install --save connect-history-api-fallback
|
---|
53 | ```
|
---|
54 |
|
---|
55 | Import the library
|
---|
56 |
|
---|
57 | ```javascript
|
---|
58 | var history = require('connect-history-api-fallback');
|
---|
59 | ```
|
---|
60 |
|
---|
61 | Now you only need to add the middleware to your application like so
|
---|
62 |
|
---|
63 | ```javascript
|
---|
64 | var connect = require('connect');
|
---|
65 |
|
---|
66 | var app = connect()
|
---|
67 | .use(history())
|
---|
68 | .listen(3000);
|
---|
69 | ```
|
---|
70 |
|
---|
71 | Of course you can also use this piece of middleware with express:
|
---|
72 |
|
---|
73 | ```javascript
|
---|
74 | var express = require('express');
|
---|
75 |
|
---|
76 | var app = express();
|
---|
77 | app.use(history());
|
---|
78 | ```
|
---|
79 |
|
---|
80 | ## Options
|
---|
81 | You can optionally pass options to the library when obtaining the middleware
|
---|
82 |
|
---|
83 | ```javascript
|
---|
84 | var middleware = history({});
|
---|
85 | ```
|
---|
86 |
|
---|
87 | ### index
|
---|
88 | Override the index (default `/index.html`)
|
---|
89 |
|
---|
90 | ```javascript
|
---|
91 | history({
|
---|
92 | index: '/default.html'
|
---|
93 | });
|
---|
94 | ```
|
---|
95 |
|
---|
96 | ### rewrites
|
---|
97 | Override the index when the request url matches a regex pattern. You can either rewrite to a static string or use a function to transform the incoming request.
|
---|
98 |
|
---|
99 | The following will rewrite a request that matches the `/\/soccer/` pattern to `/soccer.html`.
|
---|
100 | ```javascript
|
---|
101 | history({
|
---|
102 | rewrites: [
|
---|
103 | { from: /\/soccer/, to: '/soccer.html'}
|
---|
104 | ]
|
---|
105 | });
|
---|
106 | ```
|
---|
107 |
|
---|
108 | Alternatively functions can be used to have more control over the rewrite process. For instance, the following listing shows how requests to `/libs/jquery/jquery.1.12.0.min.js` and the like can be routed to `./bower_components/libs/jquery/jquery.1.12.0.min.js`. You can also make use of this if you have an API version in the URL path.
|
---|
109 | ```javascript
|
---|
110 | history({
|
---|
111 | rewrites: [
|
---|
112 | {
|
---|
113 | from: /^\/libs\/.*$/,
|
---|
114 | to: function(context) {
|
---|
115 | return '/bower_components' + context.parsedUrl.pathname;
|
---|
116 | }
|
---|
117 | }
|
---|
118 | ]
|
---|
119 | });
|
---|
120 | ```
|
---|
121 |
|
---|
122 | The function will always be called with a context object that has the following properties:
|
---|
123 |
|
---|
124 | - **parsedUrl**: Information about the URL as provided by the [URL module's](https://nodejs.org/api/url.html#url_url_parse_urlstr_parsequerystring_slashesdenotehost) `url.parse`.
|
---|
125 | - **match**: An Array of matched results as provided by `String.match(...)`.
|
---|
126 | - **request**: The HTTP request object.
|
---|
127 |
|
---|
128 |
|
---|
129 | ### verbose
|
---|
130 | This middleware does not log any information by default. If you wish to activate logging, then you can do so via the `verbose` option or by specifying a logger function.
|
---|
131 |
|
---|
132 | ```javascript
|
---|
133 | history({
|
---|
134 | verbose: true
|
---|
135 | });
|
---|
136 | ```
|
---|
137 |
|
---|
138 | Alternatively use your own logger
|
---|
139 |
|
---|
140 | ```javascript
|
---|
141 | history({
|
---|
142 | logger: console.log.bind(console)
|
---|
143 | });
|
---|
144 | ```
|
---|
145 |
|
---|
146 | ### htmlAcceptHeaders
|
---|
147 | Override the default `Accepts:` headers that are queried when matching HTML content requests (Default: `['text/html', '*/*']`).
|
---|
148 |
|
---|
149 | ```javascript
|
---|
150 | history({
|
---|
151 | htmlAcceptHeaders: ['text/html', 'application/xhtml+xml']
|
---|
152 | })
|
---|
153 | ```
|
---|
154 |
|
---|
155 | ### disableDotRule
|
---|
156 | Disables the dot rule mentioned above:
|
---|
157 |
|
---|
158 | > […] is not a direct file request, i.e. the requested path does not contain a `.` (DOT) character […]
|
---|
159 |
|
---|
160 | ```javascript
|
---|
161 | history({
|
---|
162 | disableDotRule: true
|
---|
163 | })
|
---|
164 | ```
|
---|