mirror of https://gitee.com/bigwinds/arangodb
Foxx: Starting with the Foxx User Documentation
This commit is contained in:
parent
f483f1f137
commit
74e23f8670
|
@ -1,8 +1,64 @@
|
||||||
# Foxx: Build APIs and simple web applications in ArangoDB
|
Foxx {#UserManualFoxx}
|
||||||
|
======================
|
||||||
|
|
||||||
|
Foxx: Build APIs and simple web applications in ArangoDB
|
||||||
|
========================================================
|
||||||
|
|
||||||
**WARNING: The following documentation file is pure fiction,
|
**WARNING: The following documentation file is pure fiction,
|
||||||
it is not yet finished**
|
it is not yet finished**
|
||||||
|
|
||||||
|
Foxx is an easy way to create APIs and simple web applications
|
||||||
|
from within **ArangoDB**.
|
||||||
|
It is inspired by Sinatra, the classy Ruby web framework. If FoxxApplication is Sinatra,
|
||||||
|
[ArangoDB Actions](http://www.arangodb.org/manuals/current/UserManualActions.html)
|
||||||
|
are the corresponding `Rack`. They provide all the HTTP goodness.
|
||||||
|
|
||||||
|
So let's get started, shall we?
|
||||||
|
|
||||||
|
## Foxx Application
|
||||||
|
|
||||||
|
@copydetails JSF_foxx_application_initializer
|
||||||
|
@copydetails JSF_foxx_application_start
|
||||||
|
|
||||||
|
### Handling Requests
|
||||||
|
|
||||||
|
@copydetails JSF_foxx_application_handleRequest
|
||||||
|
@copydetails JSF_foxx_application_head
|
||||||
|
@copydetails JSF_foxx_application_get
|
||||||
|
@copydetails JSF_foxx_application_post
|
||||||
|
@copydetails JSF_foxx_application_put
|
||||||
|
@copydetails JSF_foxx_application_patch
|
||||||
|
@copydetails JSF_foxx_application_delete
|
||||||
|
|
||||||
|
### Before and After Hooks
|
||||||
|
|
||||||
|
You can use the following two functions to do something
|
||||||
|
before or respectively after the normal routing process
|
||||||
|
is happening. You could use that for logging or to manipulate
|
||||||
|
the request or response (translate it to a certain format for
|
||||||
|
example).
|
||||||
|
|
||||||
|
@copydetails JSF_foxx_application_before
|
||||||
|
@copydetails JSF_foxx_application_after
|
||||||
|
|
||||||
|
### More functionality
|
||||||
|
|
||||||
|
@copydetails JSF_foxx_application_helper
|
||||||
|
@copydetails JSF_foxx_application_accepts
|
||||||
|
|
||||||
|
## The functions on a created FoxxApplication
|
||||||
|
|
||||||
|
When you have created your FoxxApplication you can now define routes
|
||||||
|
on it. You provide each with a function that will handle
|
||||||
|
the request. It gets two arguments (four, to be honest. But the
|
||||||
|
other two are not relevant for now):
|
||||||
|
|
||||||
|
* The request object
|
||||||
|
* The response object
|
||||||
|
|
||||||
|
|
||||||
|
You can find more about those in their individual sections.
|
||||||
|
|
||||||
An application build with Foxx is written in JavaScript and deployed
|
An application build with Foxx is written in JavaScript and deployed
|
||||||
to ArangoDB directly. ArangoDB serves this application, you do not
|
to ArangoDB directly. ArangoDB serves this application, you do not
|
||||||
need a separate application server.
|
need a separate application server.
|
||||||
|
|
|
@ -197,18 +197,18 @@ function SetRoutesFoxxApplicationSpec () {
|
||||||
var myFunc = function () {},
|
var myFunc = function () {},
|
||||||
routes = app.routingInfo.routes;
|
routes = app.routingInfo.routes;
|
||||||
|
|
||||||
app.requires = {
|
app.requiresLibs = {
|
||||||
a: 1
|
a: 1
|
||||||
};
|
};
|
||||||
app.models = {
|
app.requiresModels = {
|
||||||
b: 2
|
b: 2
|
||||||
};
|
};
|
||||||
app.get('/simple/route', myFunc);
|
app.get('/simple/route', myFunc);
|
||||||
app.start("myContext");
|
app.start("myContext");
|
||||||
|
|
||||||
assertEqual(app.routingInfo.routes[0].action.context, "myContext");
|
assertEqual(app.routingInfo.routes[0].action.context, "myContext");
|
||||||
assertEqual(app.routingInfo.routes[0].action.requires.a, 1);
|
assertEqual(app.routingInfo.routes[0].action.requiresLibs.a, 1);
|
||||||
assertEqual(app.routingInfo.routes[0].action.models.b, 2);
|
assertEqual(app.routingInfo.routes[0].action.requiresModels.b, 2);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,33 @@
|
||||||
/*jslint indent: 2, nomen: true, maxlen: 120, sloppy: true, vars: true */
|
/*jslint indent: 2, nomen: true, maxlen: 120, sloppy: true, vars: true */
|
||||||
/*global module, require, exports */
|
/*global module, require, exports */
|
||||||
|
|
||||||
// Foxx is an easy way to create APIs and simple web applications
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// from within **ArangoDB**.
|
/// @brief Foxx application
|
||||||
// It is inspired by Sinatra, the classy Ruby web framework. If FoxxApplication is Sinatra,
|
///
|
||||||
// [ArangoDB Actions](http://www.arangodb.org/manuals/current/UserManualActions.html)
|
/// @file
|
||||||
// are the corresponding `Rack`. They provide all the HTTP goodness.
|
///
|
||||||
//
|
/// DISCLAIMER
|
||||||
// So let's get started, shall we?
|
///
|
||||||
|
/// Copyright 2013 triagens GmbH, Cologne, Germany
|
||||||
|
///
|
||||||
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
/// you may not use this file except in compliance with the License.
|
||||||
|
/// You may obtain a copy of the License at
|
||||||
|
///
|
||||||
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
///
|
||||||
|
/// Unless required by applicable law or agreed to in writing, software
|
||||||
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
/// See the License for the specific language governing permissions and
|
||||||
|
/// limitations under the License.
|
||||||
|
///
|
||||||
|
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||||
|
///
|
||||||
|
/// @author Lucas Dohmen
|
||||||
|
/// @author Copyright 2013, triAGENS GmbH, Cologne, Germany
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// FoxxApplication uses Underscore internally. This library is wonderful.
|
|
||||||
var FoxxApplication,
|
var FoxxApplication,
|
||||||
BaseMiddleware,
|
BaseMiddleware,
|
||||||
FormatMiddleware,
|
FormatMiddleware,
|
||||||
|
@ -20,12 +38,19 @@ var FoxxApplication,
|
||||||
INTERNAL = require("internal"),
|
INTERNAL = require("internal"),
|
||||||
internal = {};
|
internal = {};
|
||||||
|
|
||||||
// ArangoDB uses a certain structure we refer to as `UrlObject`.
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// With the following function (which is only internal, and not
|
/// @fn JSF_foxx_createUrlObject
|
||||||
// exported) you can create an UrlObject with a given URL,
|
/// @brief create a new url object
|
||||||
// a constraint and a method. For example:
|
///
|
||||||
//
|
/// ArangoDB uses a certain structure we refer to as `UrlObject`.
|
||||||
// internal.createUrlObject('/lecker/gans', null, 'get')
|
/// With the following function (which is only internal, and not
|
||||||
|
/// exported) you can create an UrlObject with a given URL,
|
||||||
|
/// a constraint and a method. For example:
|
||||||
|
///
|
||||||
|
/// @EXAMPLES
|
||||||
|
/// internal.createUrlObject('/lecker/gans', null, 'get')
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
internal.createUrlObject = function (url, constraint, method) {
|
internal.createUrlObject = function (url, constraint, method) {
|
||||||
'use strict';
|
'use strict';
|
||||||
var urlObject = {};
|
var urlObject = {};
|
||||||
|
@ -44,18 +69,22 @@ internal.createUrlObject = function (url, constraint, method) {
|
||||||
return urlObject;
|
return urlObject;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ## Creating a new Application
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// And that's FoxxApplication. It's a constructor, so call it like this:
|
/// @fn JSF_foxx_application_initializer
|
||||||
//
|
/// @brief Create a new Application
|
||||||
// app = new FoxxApplication({
|
///
|
||||||
// urlPrefix: "/wiese",
|
/// And that's FoxxApplication. It's a constructor, so call it like this:
|
||||||
// templateCollection: "my_templates"
|
/// It takes two optional arguments as displayed above:
|
||||||
// })
|
/// * **The URL Prefix:** All routes you define within will be prefixed with it
|
||||||
//
|
/// * **The Template Collection:** More information in the template section
|
||||||
// It takes two optional arguments as displayed above:
|
///
|
||||||
//
|
/// @EXAMPLES
|
||||||
// * **The URL Prefix:** All routes you define within will be prefixed with it
|
/// app = new FoxxApplication({
|
||||||
// * **The Template Collection:** More information in the template section
|
/// urlPrefix: "/wiese",
|
||||||
|
/// templateCollection: "my_templates"
|
||||||
|
/// });
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
FoxxApplication = function (options) {
|
FoxxApplication = function (options) {
|
||||||
'use strict';
|
'use strict';
|
||||||
var urlPrefix, templateCollection, myMiddleware;
|
var urlPrefix, templateCollection, myMiddleware;
|
||||||
|
@ -91,23 +120,17 @@ FoxxApplication = function (options) {
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
// ## The functions on a created FoxxApplication
|
|
||||||
//
|
|
||||||
// When you have created your FoxxApplication you can now define routes
|
|
||||||
// on it. You provide each with a function that will handle
|
|
||||||
// the request. It gets two arguments (four, to be honest. But the
|
|
||||||
// other two are not relevant for now):
|
|
||||||
//
|
|
||||||
// * The request object
|
|
||||||
// * The response object
|
|
||||||
//
|
|
||||||
// You can find more about those in their individual sections.
|
|
||||||
_.extend(FoxxApplication.prototype, {
|
_.extend(FoxxApplication.prototype, {
|
||||||
// Sometimes it is a good idea to actually start the application
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// you wrote. If this precious moment has arrived, you should
|
/// @fn JSF_foxx_application_start
|
||||||
// use this function.
|
/// @brief Start the application
|
||||||
// You have to provide the start function with the `applicationContext`
|
///
|
||||||
// variable.
|
/// Sometimes it is a good idea to actually start the application
|
||||||
|
/// you wrote. If this precious moment has arrived, you should
|
||||||
|
/// use this function.
|
||||||
|
/// You have to provide the start function with the `applicationContext`
|
||||||
|
/// variable.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
start: function (context) {
|
start: function (context) {
|
||||||
'use strict';
|
'use strict';
|
||||||
var models = this.requiresModels,
|
var models = this.requiresModels,
|
||||||
|
@ -125,18 +148,24 @@ _.extend(FoxxApplication.prototype, {
|
||||||
db._collection("_routing").save(this.routingInfo);
|
db._collection("_routing").save(this.routingInfo);
|
||||||
},
|
},
|
||||||
|
|
||||||
// The `handleRequest` method is the raw way to create a new
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// route. You probably wont call it directly, but it is used
|
/// @fn JSF_foxx_application_handleRequest
|
||||||
// in the other request methods:
|
/// @brief Handle a request
|
||||||
//
|
///
|
||||||
// app.handleRequest("get", "/gaense", function (req, res) {
|
/// The `handleRequest` method is the raw way to create a new
|
||||||
// //handle the request
|
/// route. You probably wont call it directly, but it is used
|
||||||
// });
|
/// in the other request methods:
|
||||||
//
|
///
|
||||||
// When defining a route you can also define a so called 'parameterized'
|
/// When defining a route you can also define a so called 'parameterized'
|
||||||
// route like `/gaense/:stable`. In this case you can later get the value
|
/// route like `/gaense/:stable`. In this case you can later get the value
|
||||||
// the user provided for `stable` via the `params` function (see the Request
|
/// the user provided for `stable` via the `params` function (see the Request
|
||||||
// object).
|
/// object).
|
||||||
|
///
|
||||||
|
/// @EXAMPLES
|
||||||
|
/// app.handleRequest("get", "/gaense", function (req, res) {
|
||||||
|
/// //handle the request
|
||||||
|
/// });
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
handleRequest: function (method, route, argument1, argument2) {
|
handleRequest: function (method, route, argument1, argument2) {
|
||||||
'use strict';
|
'use strict';
|
||||||
var newRoute = {}, options, callback;
|
var newRoute = {}, options, callback;
|
||||||
|
@ -157,97 +186,124 @@ _.extend(FoxxApplication.prototype, {
|
||||||
this.routingInfo.routes.push(newRoute);
|
this.routingInfo.routes.push(newRoute);
|
||||||
},
|
},
|
||||||
|
|
||||||
// ### Handle a `head` request
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// This handles requests from the HTTP verb `head`.
|
/// @fn JSF_foxx_application_head
|
||||||
// As with all other requests you can give an option as the third
|
/// @brief Handle a `head` request
|
||||||
// argument, or leave it blank. You have to give a function as
|
///
|
||||||
// the last argument however. It will get a request and response
|
/// This handles requests from the HTTP verb `head`.
|
||||||
// object as its arguments
|
/// As with all other requests you can give an option as the third
|
||||||
|
/// argument, or leave it blank. You have to give a function as
|
||||||
|
/// the last argument however. It will get a request and response
|
||||||
|
/// object as its arguments
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
head: function (route, argument1, argument2) {
|
head: function (route, argument1, argument2) {
|
||||||
'use strict';
|
'use strict';
|
||||||
this.handleRequest("head", route, argument1, argument2);
|
this.handleRequest("head", route, argument1, argument2);
|
||||||
},
|
},
|
||||||
|
|
||||||
// ### Manage a `get` request
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// This handles requests from the HTTP verb `get`.
|
/// @fn JSF_foxx_application_get
|
||||||
// See above for the arguments you can give. An example:
|
/// @brief Manage a `get` request
|
||||||
//
|
///
|
||||||
// app.get('/gaense/stall', function (req, res) {
|
/// This handles requests from the HTTP verb `get`.
|
||||||
// // Take this request and deal with it!
|
/// See above for the arguments you can give. An example:
|
||||||
// });
|
///
|
||||||
|
/// @EXAMPLES
|
||||||
|
/// app.get('/gaense/stall', function (req, res) {
|
||||||
|
/// // Take this request and deal with it!
|
||||||
|
/// });
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
get: function (route, argument1, argument2) {
|
get: function (route, argument1, argument2) {
|
||||||
'use strict';
|
'use strict';
|
||||||
this.handleRequest("get", route, argument1, argument2);
|
this.handleRequest("get", route, argument1, argument2);
|
||||||
},
|
},
|
||||||
|
|
||||||
// ### Tackle a `post` request
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// This handles requests from the HTTP verb `post`.
|
/// @fn JSF_foxx_application_post
|
||||||
// See above for the arguments you can give. An example:
|
/// @brief Tackle a `post` request
|
||||||
//
|
///
|
||||||
// app.post('/gaense/stall', function (req, res) {
|
/// This handles requests from the HTTP verb `post`.
|
||||||
// // Take this request and deal with it!
|
/// See above for the arguments you can give. An example:
|
||||||
// });
|
///
|
||||||
|
/// @EXAMPLES
|
||||||
|
/// app.post('/gaense/stall', function (req, res) {
|
||||||
|
/// // Take this request and deal with it!
|
||||||
|
/// });
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
post: function (route, argument1, argument2) {
|
post: function (route, argument1, argument2) {
|
||||||
'use strict';
|
'use strict';
|
||||||
this.handleRequest("post", route, argument1, argument2);
|
this.handleRequest("post", route, argument1, argument2);
|
||||||
},
|
},
|
||||||
|
|
||||||
// ### Sort out a `put` request
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// This handles requests from the HTTP verb `put`.
|
/// @fn JSF_foxx_application_put
|
||||||
// See above for the arguments you can give. An example:
|
/// @brief Sort out a `put` request
|
||||||
//
|
///
|
||||||
// app.put('/gaense/stall', function (req, res) {
|
/// This handles requests from the HTTP verb `put`.
|
||||||
// // Take this request and deal with it!
|
/// See above for the arguments you can give. An example:
|
||||||
// });
|
///
|
||||||
|
/// @EXAMPLES
|
||||||
|
/// app.put('/gaense/stall', function (req, res) {
|
||||||
|
/// // Take this request and deal with it!
|
||||||
|
/// });
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
put: function (route, argument1, argument2) {
|
put: function (route, argument1, argument2) {
|
||||||
'use strict';
|
'use strict';
|
||||||
this.handleRequest("put", route, argument1, argument2);
|
this.handleRequest("put", route, argument1, argument2);
|
||||||
},
|
},
|
||||||
|
|
||||||
// ### Take charge of a `patch` request
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// This handles requests from the HTTP verb `patch`.
|
/// @fn JSF_foxx_application_patch
|
||||||
// See above for the arguments you can give. An example:
|
/// @brief Take charge of a `patch` request
|
||||||
//
|
///
|
||||||
// app.patch('/gaense/stall', function (req, res) {
|
/// This handles requests from the HTTP verb `patch`.
|
||||||
// // Take this request and deal with it!
|
/// See above for the arguments you can give. An example:
|
||||||
// });
|
///
|
||||||
|
/// @EXAMPLES
|
||||||
|
/// app.patch('/gaense/stall', function (req, res) {
|
||||||
|
/// // Take this request and deal with it!
|
||||||
|
/// });
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
patch: function (route, argument1, argument2) {
|
patch: function (route, argument1, argument2) {
|
||||||
'use strict';
|
'use strict';
|
||||||
this.handleRequest("patch", route, argument1, argument2);
|
this.handleRequest("patch", route, argument1, argument2);
|
||||||
},
|
},
|
||||||
|
|
||||||
// ### Respond to a `delete` request
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// This handles requests from the HTTP verb `delete`.
|
/// @fn JSF_foxx_application_delete
|
||||||
// See above for the arguments you can give.
|
/// @brief Respond to a `delete` request
|
||||||
// **A word of warning:** Do not forget that `delete` is
|
///
|
||||||
// a reserved word in JavaScript so call it as follows:
|
/// This handles requests from the HTTP verb `delete`.
|
||||||
//
|
/// See above for the arguments you can give.
|
||||||
// app['delete']('/gaense/stall', function (req, res) {
|
/// **A word of warning:** Do not forget that `delete` is
|
||||||
// // Take this request and deal with it!
|
/// a reserved word in JavaScript so call it as follows:
|
||||||
// });
|
///
|
||||||
|
/// @EXAMPLES
|
||||||
|
/// app['delete']('/gaense/stall', function (req, res) {
|
||||||
|
/// // Take this request and deal with it!
|
||||||
|
/// });
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
'delete': function (route, argument1, argument2) {
|
'delete': function (route, argument1, argument2) {
|
||||||
'use strict';
|
'use strict';
|
||||||
this.handleRequest("delete", route, argument1, argument2);
|
this.handleRequest("delete", route, argument1, argument2);
|
||||||
},
|
},
|
||||||
|
|
||||||
// ## Before and After Hooks
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// You can use the following two functions to do something
|
/// @fn JSF_foxx_application_before
|
||||||
// before or respectively after the normal routing process
|
/// @brief Before
|
||||||
// is happening. You could use that for logging or to manipulate
|
///
|
||||||
// the request or response (translate it to a certain format for
|
/// The before function takes a path on which it should watch
|
||||||
// example).
|
/// and a function that it should execute before the routing
|
||||||
|
/// takes place. If you do omit the path, the function will
|
||||||
// ### Before
|
/// be executed before each request, no matter the path.
|
||||||
// The before function takes a path on which it should watch
|
/// Your function gets a Request and a Response object.
|
||||||
// and a function that it should execute before the routing
|
/// An example:
|
||||||
// takes place. If you do omit the path, the function will
|
///
|
||||||
// be executed before each request, no matter the path.
|
/// @EXAMPLES
|
||||||
// Your function gets a Request and a Response object.
|
/// app.before('/high/way', function(req, res) {
|
||||||
// An example:
|
/// //Do some crazy request logging
|
||||||
//
|
/// });
|
||||||
// app.before('/high/way', function(req, res) {
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// //Do some crazy request logging
|
|
||||||
// });
|
|
||||||
before: function (path, func) {
|
before: function (path, func) {
|
||||||
'use strict';
|
'use strict';
|
||||||
if (_.isUndefined(func)) {
|
if (_.isUndefined(func)) {
|
||||||
|
@ -263,16 +319,21 @@ _.extend(FoxxApplication.prototype, {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// ### After
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// This works pretty similar to the before function.
|
/// @fn JSF_foxx_application_after
|
||||||
// But it acts after the execution of the handlers
|
/// @brief After
|
||||||
// (Big surprise, I suppose).
|
///
|
||||||
//
|
/// This works pretty similar to the before function.
|
||||||
// An example:
|
/// But it acts after the execution of the handlers
|
||||||
//
|
/// (Big surprise, I suppose).
|
||||||
// app.after('/high/way', function(req, res) {
|
///
|
||||||
// //Do some crazy response logging
|
/// An example:
|
||||||
// });
|
///
|
||||||
|
/// @EXAMPLES
|
||||||
|
/// app.after('/high/way', function(req, res) {
|
||||||
|
/// //Do some crazy response logging
|
||||||
|
/// });
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
after: function (path, func) {
|
after: function (path, func) {
|
||||||
'use strict';
|
'use strict';
|
||||||
if (_.isUndefined(func)) {
|
if (_.isUndefined(func)) {
|
||||||
|
@ -288,27 +349,36 @@ _.extend(FoxxApplication.prototype, {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// ## The ViewHelper concept
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// If you want to use a function inside your templates, the ViewHelpers
|
/// @fn JSF_foxx_application_helper
|
||||||
// will come to rescue you. Define them on your app like this:
|
/// @brief The ViewHelper concept
|
||||||
//
|
///
|
||||||
// app.helper("link_to", function (identifier) {
|
/// If you want to use a function inside your templates, the ViewHelpers
|
||||||
// return urlRepository[identifier];
|
/// will come to rescue you. Define them on your app like this:
|
||||||
// });
|
///
|
||||||
//
|
/// @EXAMPLES
|
||||||
// Then you can just call this function in your template's JavaScript
|
/// app.helper("link_to", function (identifier) {
|
||||||
// blocks.
|
/// return urlRepository[identifier];
|
||||||
|
/// });
|
||||||
|
///
|
||||||
|
/// Then you can just call this function in your template's JavaScript
|
||||||
|
/// blocks.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
helper: function (name, func) {
|
helper: function (name, func) {
|
||||||
'use strict';
|
'use strict';
|
||||||
this.helperCollection[name] = func;
|
this.helperCollection[name] = func;
|
||||||
},
|
},
|
||||||
|
|
||||||
// ## Shortform for using the FormatMiddleware
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
/// @fn JSF_foxx_application_accepts
|
||||||
// More information about the FormatMiddleware in the corresponding section.
|
/// @brief Shortform for using the FormatMiddleware
|
||||||
// This is a shortcut to add the middleware to your application:
|
///
|
||||||
//
|
/// More information about the FormatMiddleware in the corresponding section.
|
||||||
// app.accepts(["json"], "json");
|
/// This is a shortcut to add the middleware to your application:
|
||||||
|
///
|
||||||
|
/// @EXAMPLES
|
||||||
|
/// app.accepts(["json"], "json");
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
accepts: function (allowedFormats, defaultFormat) {
|
accepts: function (allowedFormats, defaultFormat) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
@ -322,9 +392,13 @@ _.extend(FoxxApplication.prototype, {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// ## The Base Middleware
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// The `BaseMiddleware` manipulates the request and response
|
/// @fn JSF_foxx_BaseMiddleware_initializer
|
||||||
// objects to give you a nicer API.
|
/// @brief The Base Middleware
|
||||||
|
///
|
||||||
|
/// The `BaseMiddleware` manipulates the request and response
|
||||||
|
/// objects to give you a nicer API.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
BaseMiddleware = function (templateCollection, helperCollection) {
|
BaseMiddleware = function (templateCollection, helperCollection) {
|
||||||
'use strict';
|
'use strict';
|
||||||
var middleware = function (request, response, options, next) {
|
var middleware = function (request, response, options, next) {
|
||||||
|
@ -332,29 +406,39 @@ BaseMiddleware = function (templateCollection, helperCollection) {
|
||||||
requestFunctions,
|
requestFunctions,
|
||||||
_ = require("underscore");
|
_ = require("underscore");
|
||||||
|
|
||||||
// ### The Request Object
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Every request object has the following attributes from the underlying Actions,
|
/// The Request Object
|
||||||
// amongst others:
|
/// Every request object has the following attributes from the underlying Actions,
|
||||||
//
|
/// amongst others:
|
||||||
// * path: The complete path as supplied by the user
|
///
|
||||||
//
|
/// * path: The complete path as supplied by the user
|
||||||
// FoxxApplication adds the following methods to this request object:
|
///
|
||||||
|
/// FoxxApplication adds the following methods to this request object:
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
requestFunctions = {
|
requestFunctions = {
|
||||||
// ### The superfluous `body` function
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Get the body of the request
|
/// @fn JSF_foxx_BaseMiddleware_request_body
|
||||||
|
/// @brief The superfluous `body` function
|
||||||
|
///
|
||||||
|
/// Get the body of the request
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
body: function () {
|
body: function () {
|
||||||
return this.requestBody;
|
return this.requestBody;
|
||||||
},
|
},
|
||||||
|
|
||||||
// ### The jinxed `params` function
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Get the parameters of the request. This process is two-fold:
|
/// @fn JSF_foxx_BaseMiddleware_request_params
|
||||||
//
|
/// @brief The jinxed `params` function
|
||||||
// 1. If you have defined an URL like `/test/:id` and the user
|
///
|
||||||
// requested `/test/1`, the call `params("id")` will return `1`.
|
/// Get the parameters of the request. This process is two-fold:
|
||||||
// 2. If you have defined an URL like `/test` and the user gives a
|
///
|
||||||
// query component, the query parameters will also be returned.
|
/// 1. If you have defined an URL like `/test/:id` and the user
|
||||||
// So for example if the user requested `/test?a=2`, the call
|
/// requested `/test/1`, the call `params("id")` will return `1`.
|
||||||
// `params("a")` will return `2`.
|
/// 2. If you have defined an URL like `/test` and the user gives a
|
||||||
|
/// query component, the query parameters will also be returned.
|
||||||
|
/// So for example if the user requested `/test?a=2`, the call
|
||||||
|
/// `params("a")` will return `2`.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
params: function (key) {
|
params: function (key) {
|
||||||
var ps = {};
|
var ps = {};
|
||||||
_.extend(ps, this.urlParameters);
|
_.extend(ps, this.urlParameters);
|
||||||
|
@ -363,36 +447,50 @@ BaseMiddleware = function (templateCollection, helperCollection) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// ### The Response Object
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Every response object has the following attributes from the underlying Actions:
|
/// The Response Object
|
||||||
//
|
/// Every response object has the following attributes from the underlying Actions:
|
||||||
// * contentType
|
///
|
||||||
// * responseCode
|
/// * contentType
|
||||||
// * body
|
/// * responseCode
|
||||||
// * headers (an object)
|
/// * body
|
||||||
//
|
/// * headers (an object)
|
||||||
// FoxxApplication adds the following methods to this response object.
|
///
|
||||||
|
/// FoxxApplication adds the following methods to this response object.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
responseFunctions = {
|
responseFunctions = {
|
||||||
// ### The straightforward `status` function
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Set the status code of your response, for example:
|
/// @fn JSF_foxx_BaseMiddleware_response_status
|
||||||
//
|
/// @brief The straightforward `status` function
|
||||||
// response.status(404);
|
///
|
||||||
|
/// Set the status code of your response, for example:
|
||||||
|
///
|
||||||
|
/// @EXAMPLES
|
||||||
|
/// response.status(404);
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
status: function (code) {
|
status: function (code) {
|
||||||
this.responseCode = code;
|
this.responseCode = code;
|
||||||
},
|
},
|
||||||
|
|
||||||
// ### The radical `set` function
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Set a header attribute, for example:
|
/// @fn JSF_foxx_BaseMiddleware_response_set
|
||||||
//
|
/// @brief The radical `set` function
|
||||||
// response.set("Content-Length", 123);
|
///
|
||||||
// response.set("Content-Type", "text/plain");
|
/// Set a header attribute, for example:
|
||||||
//
|
///
|
||||||
// or alternatively:
|
/// @EXAMPLES
|
||||||
//
|
/// response.set("Content-Length", 123);
|
||||||
// response.set({
|
/// response.set("Content-Type", "text/plain");
|
||||||
// "Content-Length": "123",
|
///
|
||||||
// "Content-Type": "text/plain"
|
/// or alternatively:
|
||||||
// });
|
///
|
||||||
|
/// @EXAMPLES
|
||||||
|
/// response.set({
|
||||||
|
/// "Content-Length": "123",
|
||||||
|
/// "Content-Type": "text/plain"
|
||||||
|
/// });
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
set: function (key, value) {
|
set: function (key, value) {
|
||||||
var attributes = {};
|
var attributes = {};
|
||||||
if (_.isUndefined(value)) {
|
if (_.isUndefined(value)) {
|
||||||
|
@ -412,46 +510,57 @@ BaseMiddleware = function (templateCollection, helperCollection) {
|
||||||
}, this);
|
}, this);
|
||||||
},
|
},
|
||||||
|
|
||||||
// ### The magical `json` function
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Set the content type to JSON and the body to the
|
/// @fn JSF_foxx_BaseMiddleware_response_json
|
||||||
// JSON encoded object you provided.
|
/// @brief The magical `json` function
|
||||||
//
|
///
|
||||||
// response.json({'born': 'December 12, 1915'});
|
/// Set the content type to JSON and the body to the
|
||||||
|
/// JSON encoded object you provided.
|
||||||
|
///
|
||||||
|
/// @EXAMPLES
|
||||||
|
/// response.json({'born': 'December 12, 1915'});
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
json: function (obj) {
|
json: function (obj) {
|
||||||
this.contentType = "application/json";
|
this.contentType = "application/json";
|
||||||
this.body = JSON.stringify(obj);
|
this.body = JSON.stringify(obj);
|
||||||
},
|
},
|
||||||
|
|
||||||
// ### The mysterious `render` function
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// If you initialize your FoxxApplication with a `templateCollection`,
|
/// @fn JSF_foxx_BaseMiddleware_response_render
|
||||||
// you're in luck now.
|
/// @brief The mysterious `render` function
|
||||||
// It expects documents in the following form in this collection:
|
///
|
||||||
//
|
/// If you initialize your FoxxApplication with a `templateCollection`,
|
||||||
// {
|
/// you're in luck now.
|
||||||
// path: "high/way",
|
/// It expects documents in the following form in this collection:
|
||||||
// content: "hallo <%= username %>",
|
///
|
||||||
// contentType: "text/plain",
|
/// @EXAMPLES
|
||||||
// templateLanguage: "underscore"
|
/// {
|
||||||
// }
|
/// path: "high/way",
|
||||||
//
|
/// content: "hallo <%= username %>",
|
||||||
// The `content` is the string that will be rendered by the template
|
/// contentType: "text/plain",
|
||||||
// processor. The `contentType` is the type of content that results
|
/// templateLanguage: "underscore"
|
||||||
// from this call. And with the `templateLanguage` you can choose
|
/// }
|
||||||
// your template processor. There is only one choice now: `underscore`.
|
///
|
||||||
//
|
/// The `content` is the string that will be rendered by the template
|
||||||
// If you call render, FoxxApplication will look
|
/// processor. The `contentType` is the type of content that results
|
||||||
// into the this collection and search by the path attribute.
|
/// from this call. And with the `templateLanguage` you can choose
|
||||||
// It will then render the template with the given data:
|
/// your template processor. There is only one choice now: `underscore`.
|
||||||
//
|
///
|
||||||
// response.render("high/way", {username: 'FoxxApplication'})
|
/// If you call render, FoxxApplication will look
|
||||||
//
|
/// into the this collection and search by the path attribute.
|
||||||
// Which would set the body of the response to `hello FoxxApplication` with the
|
/// It will then render the template with the given data:
|
||||||
// template defined above. It will also set the `contentType` to
|
///
|
||||||
// `text/plain` in this case.
|
/// @EXAMPLES
|
||||||
//
|
/// response.render("high/way", {username: 'FoxxApplication'})
|
||||||
// In addition to the attributes you provided, you also have access to
|
///
|
||||||
// all your view helpers. How to define them? Read above in the
|
/// Which would set the body of the response to `hello FoxxApplication` with the
|
||||||
// ViewHelper section.
|
/// template defined above. It will also set the `contentType` to
|
||||||
|
/// `text/plain` in this case.
|
||||||
|
///
|
||||||
|
/// In addition to the attributes you provided, you also have access to
|
||||||
|
/// all your view helpers. How to define them? Read above in the
|
||||||
|
/// ViewHelper section.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
render: function (templatePath, data) {
|
render: function (templatePath, data) {
|
||||||
var template;
|
var template;
|
||||||
|
|
||||||
|
@ -474,9 +583,9 @@ BaseMiddleware = function (templateCollection, helperCollection) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Now enhance the request and response as described above and call next at the
|
/// Now enhance the request and response as described above and call next at the
|
||||||
// end of this middleware (otherwise your application would never
|
/// end of this middleware (otherwise your application would never
|
||||||
// be executed. Would be a shame, really).
|
/// be executed. Would be a shame, really).
|
||||||
request = _.extend(request, requestFunctions);
|
request = _.extend(request, requestFunctions);
|
||||||
response = _.extend(response, responseFunctions);
|
response = _.extend(response, responseFunctions);
|
||||||
next();
|
next();
|
||||||
|
@ -488,32 +597,37 @@ BaseMiddleware = function (templateCollection, helperCollection) {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// ## The Format Middleware
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Unlike the `BaseMiddleware` this Middleware is only loaded if you
|
/// @brief The Format Middleware
|
||||||
// want it. This Middleware gives you Rails-like format handling via
|
///
|
||||||
// the `extension` of the URL or the accept header.
|
/// Unlike the `BaseMiddleware` this Middleware is only loaded if you
|
||||||
// Say you request an URL like `/people.json`:
|
/// want it. This Middleware gives you Rails-like format handling via
|
||||||
// The `FormatMiddleware` will set the format of the request to JSON
|
/// the `extension` of the URL or the accept header.
|
||||||
// and then delete the `.json` from the request. You can therefore write
|
/// Say you request an URL like `/people.json`:
|
||||||
// handlers that do not take an `extension` into consideration and instead
|
/// The `FormatMiddleware` will set the format of the request to JSON
|
||||||
// handle the format via a simple String.
|
/// and then delete the `.json` from the request. You can therefore write
|
||||||
// To determine the format of the request it checks the URL and then
|
/// handlers that do not take an `extension` into consideration and instead
|
||||||
// the `accept` header. If one of them gives a format or both give
|
/// handle the format via a simple String.
|
||||||
// the same, the format is set. If the formats are not the same,
|
/// To determine the format of the request it checks the URL and then
|
||||||
// an error is raised.
|
/// the `accept` header. If one of them gives a format or both give
|
||||||
//
|
/// the same, the format is set. If the formats are not the same,
|
||||||
// Use it by calling:
|
/// an error is raised.
|
||||||
//
|
///
|
||||||
// FormatMiddleware = require('foxx').FormatMiddleware;
|
/// Use it by calling:
|
||||||
// app.before("/*", FormatMiddleware.new(['json']));
|
///
|
||||||
//
|
/// @EXAMPLES
|
||||||
// or the shortcut:
|
/// FormatMiddleware = require('foxx').FormatMiddleware;
|
||||||
//
|
/// app.before("/*", FormatMiddleware.new(['json']));
|
||||||
// app.accepts(['json']);
|
///
|
||||||
//
|
/// or the shortcut:
|
||||||
// In both forms you can give a default format as a second parameter,
|
///
|
||||||
// if no format could be determined. If you give no `defaultFormat` this
|
/// @EXAMPLES
|
||||||
// case will be handled as an error.
|
/// app.accepts(['json']);
|
||||||
|
///
|
||||||
|
/// In both forms you can give a default format as a second parameter,
|
||||||
|
/// if no format could be determined. If you give no `defaultFormat` this
|
||||||
|
/// case will be handled as an error.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
FormatMiddleware = function (allowedFormats, defaultFormat) {
|
FormatMiddleware = function (allowedFormats, defaultFormat) {
|
||||||
'use strict';
|
'use strict';
|
||||||
var stringRepresentation, middleware = function (request, response, options, next) {
|
var stringRepresentation, middleware = function (request, response, options, next) {
|
||||||
|
@ -588,8 +702,8 @@ FormatMiddleware = function (allowedFormats, defaultFormat) {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// We finish off with exporting FoxxApplication and the middlewares.
|
/// We finish off with exporting FoxxApplication and the middlewares.
|
||||||
// Everything else will remain our secret.
|
/// Everything else will remain our secret.
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief loads a manifest file
|
/// @brief loads a manifest file
|
||||||
|
@ -654,11 +768,15 @@ exports.FoxxApplication = FoxxApplication;
|
||||||
exports.BaseMiddleware = BaseMiddleware;
|
exports.BaseMiddleware = BaseMiddleware;
|
||||||
exports.FormatMiddleware = FormatMiddleware;
|
exports.FormatMiddleware = FormatMiddleware;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// --SECTION-- END-OF-FILE
|
/// @}
|
||||||
// -----------------------------------------------------------------------------
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Local Variables:
|
/// -----------------------------------------------------------------------------
|
||||||
// mode: outline-minor
|
/// --SECTION-- END-OF-FILE
|
||||||
// outline-regexp: "/// @brief\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}\\|/\\*jslint"
|
/// -----------------------------------------------------------------------------
|
||||||
// End:
|
|
||||||
|
/// Local Variables:
|
||||||
|
/// mode: outline-minor
|
||||||
|
/// outline-regexp: "/// @brief\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}\\|/\\*jslint"
|
||||||
|
/// End:
|
||||||
|
|
Loading…
Reference in New Issue