@@ -40,8 +40,15 @@ const requestHandler = async (core, parsedUrl, response) => {
40
40
}
41
41
42
42
const path = parsedUrl . pathname . substring ( "/guide" . length ) ;
43
- const type = contentType ( path ) ;
44
- const file = await core . file ( path , type ) ;
43
+ const redirect = await checkRedirects ( core , path ) ;
44
+ if ( redirect ) {
45
+ response . statusCode = 301 ;
46
+ response . setHeader ( 'Location' , redirect ) ;
47
+ response . end ( ) ;
48
+ return ;
49
+ }
50
+
51
+ const file = await core . file ( path ) ;
45
52
if ( file === "dir" ) {
46
53
response . statusCode = 301 ;
47
54
const sep = parsedUrl . pathname . endsWith ( '/' ) ? '' : '/' ;
@@ -55,6 +62,7 @@ const requestHandler = async (core, parsedUrl, response) => {
55
62
return ;
56
63
}
57
64
65
+ const type = contentType ( path ) ;
58
66
response . setHeader ( 'Content-Type' , type ) ;
59
67
if ( file . hasTemplate && ! path . endsWith ( "toc.html" ) && type === "text/html; charset=utf-8" ) {
60
68
const template = Template ( file . template ) ;
@@ -126,6 +134,47 @@ const hostPrefix = host => {
126
134
return host . substring ( 0 , dot ) ;
127
135
} ;
128
136
137
+ const checkRedirects = async ( core , path ) => {
138
+ /*
139
+ * This parses the nginx redirects.conf file we have in the built docs and
140
+ * performs the redirects. It makes no effort to properly emulate nginx. It
141
+ * just runs the regexes from start to finish. Which is fine becaues of the
142
+ * redirects that we have. But it is ugly.
143
+ *
144
+ * It also doesen't make any effort to be fast or efficient, buffering the
145
+ * entire file into memory then splitting it into lines and compiling all of
146
+ * the regexes on the fly. We can absolutely do better. But this feels like
147
+ * a fine place to start.
148
+ */
149
+ // TODO Rebuild redirects file without nginx stuff. And stream it properly.
150
+ let target = "/guide" + path ;
151
+ const redirectsStart = Date . now ( ) ;
152
+ const streamToString = stream => {
153
+ const chunks = [ ]
154
+ return new Promise ( ( resolve , reject ) => {
155
+ stream . on ( 'data' , chunk => chunks . push ( chunk ) ) ;
156
+ stream . on ( 'error' , reject ) ;
157
+ stream . on ( 'end' , ( ) => resolve ( Buffer . concat ( chunks ) . toString ( 'utf8' ) ) ) ;
158
+ } ) ;
159
+ }
160
+ const redirectsStream = await core . redirects ( ) ;
161
+ if ( ! redirectsStream ) {
162
+ // If we don't have the redirects file we skip redirects.
163
+ return ;
164
+ }
165
+ const redirectsString = await streamToString ( redirectsStream ) ;
166
+ for ( const line of redirectsString . split ( '\n' ) ) {
167
+ if ( ! line . startsWith ( "rewrite" ) ) {
168
+ continue ;
169
+ }
170
+ const [ _marker , regexText , replacement ] = line . split ( ' ' ) ;
171
+ const regex = new RegExp ( regexText . replace ( '(?i)' , '' ) , 'i' ) ;
172
+ target = target . replace ( regex , replacement ) ;
173
+ }
174
+ console . log ( "took" , Date . now ( ) - redirectsStart ) ;
175
+ return "/guide" + path === target ? null : target ;
176
+ }
177
+
129
178
module . exports = Core => {
130
179
const server = http . createServer ( ( request , response ) => {
131
180
const parsedUrl = url . parse ( request . url ) ;
0 commit comments