Skip to content

Commit

Permalink
Merge pull request hapijs#602 from walmartlabs/user/eran
Browse files Browse the repository at this point in the history
Relative paths
  • Loading branch information
geek committed Feb 28, 2013
2 parents 836890a + 8d6dac5 commit 1ab70bf
Show file tree
Hide file tree
Showing 17 changed files with 1,133 additions and 1,046 deletions.
28 changes: 14 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ with everything else.

For the latest updates and release information follow [@hapijs](https://twitter.com/hapijs) on twitter.

Current version: **0.14.3**
Current version: **0.15.0**

[![Build Status](https://secure.travis-ci.org/walmartlabs/hapi.png)](http://travis-ci.org/walmartlabs/hapi)
<img src="https://raw.github.com/olivierlacan/shields/master/coveralls/coveralls_100.png" />
Expand Down Expand Up @@ -97,20 +97,20 @@ The **hapi** route handler can be used to easily serve files, directories, rende
```javascript
server.route({
method: 'GET',
path: '/{path*}',
handler: {
directory: { path: './public', listing: false, index: true }
}
path: '/{path*}',
handler: {
directory: { path: './public', listing: false, index: true }
}
});
```

Create a folder named _'public'_ and add a _'index.html'_ file in the folder with the following contents:
```html
<html>
<head><title>Hello Static</title></head>
<body>
Hello Static
</body>
<head><title>Hello Static</title></head>
<body>
Hello Static
</body>
</html>
```

Expand All @@ -127,10 +127,10 @@ npm install handlebars
Next create a directory named _'templates'_ that will contain the template files. In this directory create a _'index.html'_ with the following contents:
```html
<html>
<head><title>{{greeting}}</title></head>
<body>
{{greeting}}
</body>
<head><title>{{greeting}}</title></head>
<body>
{{greeting}}
</body>
</html>
```

Expand All @@ -154,7 +154,7 @@ var server = new Hapi.Server('localhost', 8000, options);
var hello = {
handler: function (request) {

// Render the view with the custom greeting
// Render the view with the custom greeting
request.reply.view('index.html', { greeting: 'hello world' }).send();
}
};
Expand Down
19 changes: 15 additions & 4 deletions docs/Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,10 @@ function onRequest(request, next) {

**hapi** provides built-in support for serving static files and directories as described in [File](#file) and [Directory](#directory).
When these handlers are provided with relative paths, the `files.relativeTo` server option determines how these paths are resolved
and defaults to _'routes'_:
and defaults to _'cwd'_:
- _'cwd'_ - relative paths are resolved using the active process path (_'process.cwd()'_).
- _'routes'_ - relative paths are resolved based on the location of the files in which the server's _'route()'_ method is called. This means the location of the source code determines the location of the static resources when using relative paths.
- _'process'_ - relative paths are resolved using the active process path (_'process.cwd()'_).
- an absolute prefix path - an absolute path (e.g. '/path') used as a prefix for all relative paths.


### Views
Expand Down Expand Up @@ -799,7 +800,7 @@ It is possible with hapi to setup a reverse proxy for routes. This is especiall
- `host` - The host to proxy requests to. The same path on the client request will be used as the path to the host.
- `port` - The port to use when making a request to the host.
- `protocol` - The protocol to use when making a request to the proxied host (http or https)
- `mapUri` - A function that receives the clients request and a passes the URI to a callback to make the proxied request to. If host is set mapUri cannot be used, set either host or mapUri.
- `mapUri` - A function used to map the request URI to the proxied URI. The function signature is _function (request, callback)_ where 'request' is the incoming request object, and callback is 'function (err, uri)'. Cannot be used together with `host`, `port`, or `protocol`.
- `postResponse` - A function that will be executed before sending the response to the client for requests that can be cached. Use this for any custom error handling of responses from the proxied endpoint.
- `httpClient` - A function that should make the request to the remote server and use execute the callback with a response. By default this uses _'request'_ as the module. The signature is (options, callback) where options will contain a url and method.

Expand All @@ -814,6 +815,16 @@ http.route({ method: 'GET', path: '/', handler: { proxy: { protocol: 'http', hos
http.start();
```
Using `mapUri`:
```javascript
var mapper = function (request, callback) {

callback(null, 'https://www.google.com/?q=' + request.param.term);
};

http.route({ method: 'GET', path: '/{term}', handler: { proxy: { mapUri: mapper } } });
```
#### File
Expand All @@ -824,7 +835,7 @@ configured with a static file path. For example:
```javascript
// Create Hapi server
var http = new Hapi.Server('0.0.0.0', 8080, { files: { relativeTo: 'process' } });
var http = new Hapi.Server('0.0.0.0', 8080, { files: { relativeTo: 'cwd' } });

// Serve index.html file up a directory in the public folder
http.route({ method: 'GET', path: '/', handler: { file: './public/index.html' } });
Expand Down
2 changes: 1 addition & 1 deletion lib/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ exports.server = {
// Files path

files: {
relativeTo: 'routes' // Determines what file and directory handlers use to base relative paths off: 'routes', 'process'
relativeTo: 'cwd' // Determines what file and directory handlers use to base relative paths off: 'cwd', 'routes', or absolute path prefix
},

// timeout limits
Expand Down
101 changes: 58 additions & 43 deletions lib/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ var Response = require('./response');
var internals = {};


exports.fileHandler = function (route, filePath) {
exports.fileHandler = function (route, filePath) {

Utils.assert(filePath && (typeof filePath === 'function' || typeof filePath === 'string'), 'Invalid file path');
Utils.assert(typeof filePath !== 'string' || route.params.length === 0, 'Route path with static file path cannot contain a parameter');
Expand All @@ -20,38 +20,38 @@ exports.fileHandler = function (route, filePath) {

// Normalize static string path

if (typeof filePath === 'string') {
if (typeof filePath === 'string') {
var staticPath = filePath;
if (staticPath[0] !== '/') {
staticPath = absolutePath + '/' + staticPath;
}
if (staticPath[0] !== '/') {
staticPath = absolutePath + '/' + staticPath;
}
}

var handler = function (request) {
var handler = function (request) {

var path = null;

if (typeof filePath === 'function') {
if (typeof filePath === 'function') {
path = filePath(request);

// Normalize function string path

if (path[0] !== '/') {
path = absolutePath + '/' + path;
}
if (path[0] !== '/') {
path = absolutePath + '/' + path;
}
}
else {
path = staticPath;
else {
path = staticPath;
}

return request.reply(new Response.File(path));
return request.reply(new Response.File(path));
}

return handler;
return handler;
};


exports.directoryHandler = function (route, options) {
exports.directoryHandler = function (route, options) {

Utils.assert(options, 'Options must exist');
Utils.assert(typeof options === 'object' && options.path, 'Options must be an object with a path');
Expand All @@ -64,8 +64,8 @@ exports.directoryHandler = function (route, options) {

// Normalize static string path

if (typeof settings.path === 'string') {
settings.path = [settings.path];
if (typeof settings.path === 'string') {
settings.path = [settings.path];
}

var normalize = function (path) {
Expand All @@ -90,71 +90,86 @@ exports.directoryHandler = function (route, options) {
});
}

var handler = function (request) {
var handler = function (request) {

var paths = normalized;
if (typeof settings.path === 'function') {
paths = [normalize(settings.path(request))];
if (typeof settings.path === 'function') {
paths = [normalize(settings.path(request))];
}

// Append parameter

var selection = null;
if (request._paramsArray[0]) {
if (request._paramsArray[0].indexOf('..') !== -1) {
return request.reply(Boom.forbidden());
if (request._paramsArray[0]) {
if (request._paramsArray[0].indexOf('..') !== -1) {
return request.reply(Boom.forbidden());
}

selection = request._paramsArray[0];
selection = request._paramsArray[0];
}

// Generate response

var response = new Response.Directory(paths, {
var response = new Response.Directory(paths, {

resource: request.path,
selection: selection,
index: settings.index,
listing: settings.listing,
showHidden: settings.showHidden
showHidden: settings.showHidden
});

return request.reply(response);
return request.reply(response);
};

return handler;
return handler;
};


internals.absolutePath = function (route) {
internals.absolutePath = function (route) {

Utils.assert(route.server.settings.files && route.server.settings.files.relativeTo && ['routes', 'process'].indexOf(route.server.settings.files.relativeTo) !== -1, 'Invalid server files.relativeTo configuration');
var relativeTo = route.server.settings.files && route.server.settings.files.relativeTo;
Utils.assert(relativeTo && (relativeTo[0] === '/' || ['cwd', 'routes'].indexOf(relativeTo) !== -1), 'Invalid server files.relativeTo configuration');

// Plugin

if (route.env.path) {
return route.env.path;
}

// 'cwd'

if (relativeTo === 'cwd') {
return '.';
}

// 'routes'

if (route.server.settings.files.relativeTo === 'routes') {
return internals.getRouteSourceFilePath();
if (relativeTo === 'routes') {
return internals.getRouteSourceFilePath();
}

// 'process'
// '/path'

return process.cwd();
return relativeTo;
};


internals.getRouteSourceFilePath = function () {
internals.getRouteSourceFilePath = function () {

var stack = Utils.callStack();
var callerPos = 0;

stack.forEach(function (stackLine, i) {
for (var i = 0, il = stack.length; i < il; ++i) {
var stackLine = stack[i];
if (stackLine[3] &&
stackLine[3].indexOf('internals.Server.route') !== -1) { // The file that added the route will appear after the call to route

if (stackLine[3] && stackLine[3].indexOf('internals.Server.route') !== -1) { // The file that added the route will appear after the call to route
callerPos = i + 1;
return;
}
});
callerPos = i + 1;
break;
}
}

return Path.dirname(stack[callerPos][0]);
return Path.dirname(stack[callerPos][0]);
};

Loading

0 comments on commit 1ab70bf

Please sign in to comment.