source: trip-planner-front/node_modules/connect/index.js@ b738035

Last change on this file since b738035 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 5.9 KB
RevLine 
[6a3a178]1/*!
2 * connect
3 * Copyright(c) 2010 Sencha Inc.
4 * Copyright(c) 2011 TJ Holowaychuk
5 * Copyright(c) 2015 Douglas Christopher Wilson
6 * MIT Licensed
7 */
8
9'use strict';
10
11/**
12 * Module dependencies.
13 * @private
14 */
15
16var debug = require('debug')('connect:dispatcher');
17var EventEmitter = require('events').EventEmitter;
18var finalhandler = require('finalhandler');
19var http = require('http');
20var merge = require('utils-merge');
21var parseUrl = require('parseurl');
22
23/**
24 * Module exports.
25 * @public
26 */
27
28module.exports = createServer;
29
30/**
31 * Module variables.
32 * @private
33 */
34
35var env = process.env.NODE_ENV || 'development';
36var proto = {};
37
38/* istanbul ignore next */
39var defer = typeof setImmediate === 'function'
40 ? setImmediate
41 : function(fn){ process.nextTick(fn.bind.apply(fn, arguments)) }
42
43/**
44 * Create a new connect server.
45 *
46 * @return {function}
47 * @public
48 */
49
50function createServer() {
51 function app(req, res, next){ app.handle(req, res, next); }
52 merge(app, proto);
53 merge(app, EventEmitter.prototype);
54 app.route = '/';
55 app.stack = [];
56 return app;
57}
58
59/**
60 * Utilize the given middleware `handle` to the given `route`,
61 * defaulting to _/_. This "route" is the mount-point for the
62 * middleware, when given a value other than _/_ the middleware
63 * is only effective when that segment is present in the request's
64 * pathname.
65 *
66 * For example if we were to mount a function at _/admin_, it would
67 * be invoked on _/admin_, and _/admin/settings_, however it would
68 * not be invoked for _/_, or _/posts_.
69 *
70 * @param {String|Function|Server} route, callback or server
71 * @param {Function|Server} callback or server
72 * @return {Server} for chaining
73 * @public
74 */
75
76proto.use = function use(route, fn) {
77 var handle = fn;
78 var path = route;
79
80 // default route to '/'
81 if (typeof route !== 'string') {
82 handle = route;
83 path = '/';
84 }
85
86 // wrap sub-apps
87 if (typeof handle.handle === 'function') {
88 var server = handle;
89 server.route = path;
90 handle = function (req, res, next) {
91 server.handle(req, res, next);
92 };
93 }
94
95 // wrap vanilla http.Servers
96 if (handle instanceof http.Server) {
97 handle = handle.listeners('request')[0];
98 }
99
100 // strip trailing slash
101 if (path[path.length - 1] === '/') {
102 path = path.slice(0, -1);
103 }
104
105 // add the middleware
106 debug('use %s %s', path || '/', handle.name || 'anonymous');
107 this.stack.push({ route: path, handle: handle });
108
109 return this;
110};
111
112/**
113 * Handle server requests, punting them down
114 * the middleware stack.
115 *
116 * @private
117 */
118
119proto.handle = function handle(req, res, out) {
120 var index = 0;
121 var protohost = getProtohost(req.url) || '';
122 var removed = '';
123 var slashAdded = false;
124 var stack = this.stack;
125
126 // final function handler
127 var done = out || finalhandler(req, res, {
128 env: env,
129 onerror: logerror
130 });
131
132 // store the original URL
133 req.originalUrl = req.originalUrl || req.url;
134
135 function next(err) {
136 if (slashAdded) {
137 req.url = req.url.substr(1);
138 slashAdded = false;
139 }
140
141 if (removed.length !== 0) {
142 req.url = protohost + removed + req.url.substr(protohost.length);
143 removed = '';
144 }
145
146 // next callback
147 var layer = stack[index++];
148
149 // all done
150 if (!layer) {
151 defer(done, err);
152 return;
153 }
154
155 // route data
156 var path = parseUrl(req).pathname || '/';
157 var route = layer.route;
158
159 // skip this layer if the route doesn't match
160 if (path.toLowerCase().substr(0, route.length) !== route.toLowerCase()) {
161 return next(err);
162 }
163
164 // skip if route match does not border "/", ".", or end
165 var c = path.length > route.length && path[route.length];
166 if (c && c !== '/' && c !== '.') {
167 return next(err);
168 }
169
170 // trim off the part of the url that matches the route
171 if (route.length !== 0 && route !== '/') {
172 removed = route;
173 req.url = protohost + req.url.substr(protohost.length + removed.length);
174
175 // ensure leading slash
176 if (!protohost && req.url[0] !== '/') {
177 req.url = '/' + req.url;
178 slashAdded = true;
179 }
180 }
181
182 // call the layer handle
183 call(layer.handle, route, err, req, res, next);
184 }
185
186 next();
187};
188
189/**
190 * Listen for connections.
191 *
192 * This method takes the same arguments
193 * as node's `http.Server#listen()`.
194 *
195 * HTTP and HTTPS:
196 *
197 * If you run your application both as HTTP
198 * and HTTPS you may wrap them individually,
199 * since your Connect "server" is really just
200 * a JavaScript `Function`.
201 *
202 * var connect = require('connect')
203 * , http = require('http')
204 * , https = require('https');
205 *
206 * var app = connect();
207 *
208 * http.createServer(app).listen(80);
209 * https.createServer(options, app).listen(443);
210 *
211 * @return {http.Server}
212 * @api public
213 */
214
215proto.listen = function listen() {
216 var server = http.createServer(this);
217 return server.listen.apply(server, arguments);
218};
219
220/**
221 * Invoke a route handle.
222 * @private
223 */
224
225function call(handle, route, err, req, res, next) {
226 var arity = handle.length;
227 var error = err;
228 var hasError = Boolean(err);
229
230 debug('%s %s : %s', handle.name || '<anonymous>', route, req.originalUrl);
231
232 try {
233 if (hasError && arity === 4) {
234 // error-handling middleware
235 handle(err, req, res, next);
236 return;
237 } else if (!hasError && arity < 4) {
238 // request-handling middleware
239 handle(req, res, next);
240 return;
241 }
242 } catch (e) {
243 // replace the error
244 error = e;
245 }
246
247 // continue
248 next(error);
249}
250
251/**
252 * Log error using console.error.
253 *
254 * @param {Error} err
255 * @private
256 */
257
258function logerror(err) {
259 if (env !== 'test') console.error(err.stack || err.toString());
260}
261
262/**
263 * Get get protocol + host for a URL.
264 *
265 * @param {string} url
266 * @private
267 */
268
269function getProtohost(url) {
270 if (url.length === 0 || url[0] === '/') {
271 return undefined;
272 }
273
274 var fqdnIndex = url.indexOf('://')
275
276 return fqdnIndex !== -1 && url.lastIndexOf('?', fqdnIndex) === -1
277 ? url.substr(0, url.indexOf('/', 3 + fqdnIndex))
278 : undefined;
279}
Note: See TracBrowser for help on using the repository browser.