From 74e23f8670de3a2f60e7369b2642915d540deb9e Mon Sep 17 00:00:00 2001 From: Lucas Dohmen Date: Mon, 25 Mar 2013 09:50:32 +0100 Subject: [PATCH] Foxx: Starting with the Foxx User Documentation --- Documentation/UserManual/Foxx.md | 58 ++- js/common/tests/shell-foxx.js | 8 +- js/server/modules/org/arangodb/foxx.js | 638 +++++++++++++++---------- 3 files changed, 439 insertions(+), 265 deletions(-) diff --git a/Documentation/UserManual/Foxx.md b/Documentation/UserManual/Foxx.md index 4d25168a41..9eda1001ba 100644 --- a/Documentation/UserManual/Foxx.md +++ b/Documentation/UserManual/Foxx.md @@ -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, 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 to ArangoDB directly. ArangoDB serves this application, you do not need a separate application server. diff --git a/js/common/tests/shell-foxx.js b/js/common/tests/shell-foxx.js index 3ed0ae2ed8..2851a9f671 100644 --- a/js/common/tests/shell-foxx.js +++ b/js/common/tests/shell-foxx.js @@ -197,18 +197,18 @@ function SetRoutesFoxxApplicationSpec () { var myFunc = function () {}, routes = app.routingInfo.routes; - app.requires = { + app.requiresLibs = { a: 1 }; - app.models = { + app.requiresModels = { b: 2 }; app.get('/simple/route', myFunc); app.start("myContext"); assertEqual(app.routingInfo.routes[0].action.context, "myContext"); - assertEqual(app.routingInfo.routes[0].action.requires.a, 1); - assertEqual(app.routingInfo.routes[0].action.models.b, 2); + assertEqual(app.routingInfo.routes[0].action.requiresLibs.a, 1); + assertEqual(app.routingInfo.routes[0].action.requiresModels.b, 2); } }; } diff --git a/js/server/modules/org/arangodb/foxx.js b/js/server/modules/org/arangodb/foxx.js index 9e9565bfe1..ca20b9db2b 100644 --- a/js/server/modules/org/arangodb/foxx.js +++ b/js/server/modules/org/arangodb/foxx.js @@ -1,15 +1,33 @@ /*jslint indent: 2, nomen: true, maxlen: 120, sloppy: true, vars: true */ /*global module, require, exports */ -// 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? +//////////////////////////////////////////////////////////////////////////////// +/// @brief Foxx application +/// +/// @file +/// +/// DISCLAIMER +/// +/// 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, BaseMiddleware, FormatMiddleware, @@ -20,12 +38,19 @@ var FoxxApplication, INTERNAL = require("internal"), internal = {}; -// ArangoDB uses a certain structure we refer to as `UrlObject`. -// 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: -// -// internal.createUrlObject('/lecker/gans', null, 'get') +//////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_foxx_createUrlObject +/// @brief create a new url object +/// +/// ArangoDB uses a certain structure we refer to as `UrlObject`. +/// 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) { 'use strict'; var urlObject = {}; @@ -44,18 +69,22 @@ internal.createUrlObject = function (url, constraint, method) { return urlObject; }; -// ## Creating a new Application -// And that's FoxxApplication. It's a constructor, so call it like this: -// -// app = new FoxxApplication({ -// urlPrefix: "/wiese", -// 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 +//////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_foxx_application_initializer +/// @brief Create a new Application +/// +/// And that's FoxxApplication. It's a constructor, so call it like this: +/// 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 +/// +/// @EXAMPLES +/// app = new FoxxApplication({ +/// urlPrefix: "/wiese", +/// templateCollection: "my_templates" +/// }); +//////////////////////////////////////////////////////////////////////////////// + FoxxApplication = function (options) { 'use strict'; 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, { - // 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. +//////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_foxx_application_start +/// @brief Start the application +/// +/// 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) { 'use strict'; var models = this.requiresModels, @@ -125,18 +148,24 @@ _.extend(FoxxApplication.prototype, { 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 - // in the other request methods: - // - // app.handleRequest("get", "/gaense", function (req, res) { - // //handle the request - // }); - // - // 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 - // the user provided for `stable` via the `params` function (see the Request - // object). +//////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_foxx_application_handleRequest +/// @brief Handle a request +/// +/// The `handleRequest` method is the raw way to create a new +/// 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' +/// 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 +/// object). +/// +/// @EXAMPLES +/// app.handleRequest("get", "/gaense", function (req, res) { +/// //handle the request +/// }); +//////////////////////////////////////////////////////////////////////////////// handleRequest: function (method, route, argument1, argument2) { 'use strict'; var newRoute = {}, options, callback; @@ -157,97 +186,124 @@ _.extend(FoxxApplication.prototype, { this.routingInfo.routes.push(newRoute); }, - // ### Handle a `head` request - // This handles requests from the HTTP verb `head`. - // 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 +//////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_foxx_application_head +/// @brief Handle a `head` request +/// +/// This handles requests from the HTTP verb `head`. +/// 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) { 'use strict'; this.handleRequest("head", route, argument1, argument2); }, - // ### Manage a `get` request - // This handles requests from the HTTP verb `get`. - // See above for the arguments you can give. An example: - // - // app.get('/gaense/stall', function (req, res) { - // // Take this request and deal with it! - // }); +//////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_foxx_application_get +/// @brief Manage a `get` request +/// +/// This handles requests from the HTTP verb `get`. +/// 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) { 'use strict'; this.handleRequest("get", route, argument1, argument2); }, - // ### Tackle a `post` request - // This handles requests from the HTTP verb `post`. - // See above for the arguments you can give. An example: - // - // app.post('/gaense/stall', function (req, res) { - // // Take this request and deal with it! - // }); +//////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_foxx_application_post +/// @brief Tackle a `post` request +/// +/// This handles requests from the HTTP verb `post`. +/// 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) { 'use strict'; this.handleRequest("post", route, argument1, argument2); }, - // ### Sort out a `put` request - // This handles requests from the HTTP verb `put`. - // See above for the arguments you can give. An example: - // - // app.put('/gaense/stall', function (req, res) { - // // Take this request and deal with it! - // }); +//////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_foxx_application_put +/// @brief Sort out a `put` request +/// +/// This handles requests from the HTTP verb `put`. +/// 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) { 'use strict'; this.handleRequest("put", route, argument1, argument2); }, - // ### Take charge of a `patch` request - // This handles requests from the HTTP verb `patch`. - // See above for the arguments you can give. An example: - // - // app.patch('/gaense/stall', function (req, res) { - // // Take this request and deal with it! - // }); +//////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_foxx_application_patch +/// @brief Take charge of a `patch` request +/// +/// This handles requests from the HTTP verb `patch`. +/// 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) { 'use strict'; this.handleRequest("patch", route, argument1, argument2); }, - // ### Respond to a `delete` request - // This handles requests from the HTTP verb `delete`. - // See above for the arguments you can give. - // **A word of warning:** Do not forget that `delete` is - // a reserved word in JavaScript so call it as follows: - // - // app['delete']('/gaense/stall', function (req, res) { - // // Take this request and deal with it! - // }); +//////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_foxx_application_delete +/// @brief Respond to a `delete` request +/// +/// This handles requests from the HTTP verb `delete`. +/// See above for the arguments you can give. +/// **A word of warning:** Do not forget that `delete` is +/// 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) { 'use strict'; this.handleRequest("delete", route, argument1, argument2); }, - // ## 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). - - // ### Before - // The before function takes a path on which it should watch - // and a function that it should execute before the routing - // takes place. If you do omit the path, the function will - // be executed before each request, no matter the path. - // Your function gets a Request and a Response object. - // An example: - // - // app.before('/high/way', function(req, res) { - // //Do some crazy request logging - // }); +//////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_foxx_application_before +/// @brief Before +/// +/// The before function takes a path on which it should watch +/// and a function that it should execute before the routing +/// takes place. If you do omit the path, the function will +/// be executed before each request, no matter the path. +/// Your function gets a Request and a Response object. +/// An example: +/// +/// @EXAMPLES +/// app.before('/high/way', function(req, res) { +/// //Do some crazy request logging +/// }); +//////////////////////////////////////////////////////////////////////////////// before: function (path, func) { 'use strict'; if (_.isUndefined(func)) { @@ -263,16 +319,21 @@ _.extend(FoxxApplication.prototype, { }); }, - // ### After - // This works pretty similar to the before function. - // But it acts after the execution of the handlers - // (Big surprise, I suppose). - // - // An example: - // - // app.after('/high/way', function(req, res) { - // //Do some crazy response logging - // }); +//////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_foxx_application_after +/// @brief After +/// +/// This works pretty similar to the before function. +/// But it acts after the execution of the handlers +/// (Big surprise, I suppose). +/// +/// An example: +/// +/// @EXAMPLES +/// app.after('/high/way', function(req, res) { +/// //Do some crazy response logging +/// }); +//////////////////////////////////////////////////////////////////////////////// after: function (path, func) { 'use strict'; 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 - // will come to rescue you. Define them on your app like this: - // - // app.helper("link_to", function (identifier) { - // return urlRepository[identifier]; - // }); - // - // Then you can just call this function in your template's JavaScript - // blocks. +//////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_foxx_application_helper +/// @brief The ViewHelper concept +/// +/// If you want to use a function inside your templates, the ViewHelpers +/// will come to rescue you. Define them on your app like this: +/// +/// @EXAMPLES +/// app.helper("link_to", function (identifier) { +/// return urlRepository[identifier]; +/// }); +/// +/// Then you can just call this function in your template's JavaScript +/// blocks. +//////////////////////////////////////////////////////////////////////////////// helper: function (name, func) { 'use strict'; this.helperCollection[name] = func; }, - // ## Shortform for using the FormatMiddleware - // - // More information about the FormatMiddleware in the corresponding section. - // This is a shortcut to add the middleware to your application: - // - // app.accepts(["json"], "json"); +//////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_foxx_application_accepts +/// @brief Shortform for using the FormatMiddleware +/// +/// More information about the FormatMiddleware in the corresponding section. +/// This is a shortcut to add the middleware to your application: +/// +/// @EXAMPLES +/// app.accepts(["json"], "json"); +//////////////////////////////////////////////////////////////////////////////// accepts: function (allowedFormats, defaultFormat) { 'use strict'; @@ -322,9 +392,13 @@ _.extend(FoxxApplication.prototype, { }); -// ## The Base Middleware -// The `BaseMiddleware` manipulates the request and response -// objects to give you a nicer API. +//////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_foxx_BaseMiddleware_initializer +/// @brief The Base Middleware +/// +/// The `BaseMiddleware` manipulates the request and response +/// objects to give you a nicer API. +//////////////////////////////////////////////////////////////////////////////// BaseMiddleware = function (templateCollection, helperCollection) { 'use strict'; var middleware = function (request, response, options, next) { @@ -332,29 +406,39 @@ BaseMiddleware = function (templateCollection, helperCollection) { requestFunctions, _ = require("underscore"); - // ### The Request Object - // Every request object has the following attributes from the underlying Actions, - // amongst others: - // - // * path: The complete path as supplied by the user - // - // FoxxApplication adds the following methods to this request object: +//////////////////////////////////////////////////////////////////////////////// +/// The Request Object +/// Every request object has the following attributes from the underlying Actions, +/// amongst others: +/// +/// * path: The complete path as supplied by the user +/// +/// FoxxApplication adds the following methods to this request object: +//////////////////////////////////////////////////////////////////////////////// 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 () { return this.requestBody; }, - // ### The jinxed `params` function - // Get the parameters of the request. This process is two-fold: - // - // 1. If you have defined an URL like `/test/:id` and the user - // requested `/test/1`, the call `params("id")` will return `1`. - // 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`. +//////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_foxx_BaseMiddleware_request_params +/// @brief The jinxed `params` function +/// +/// Get the parameters of the request. This process is two-fold: +/// +/// 1. If you have defined an URL like `/test/:id` and the user +/// requested `/test/1`, the call `params("id")` will return `1`. +/// 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) { var ps = {}; _.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: - // - // * contentType - // * responseCode - // * body - // * headers (an object) - // - // FoxxApplication adds the following methods to this response object. +//////////////////////////////////////////////////////////////////////////////// +/// The Response Object +/// Every response object has the following attributes from the underlying Actions: +/// +/// * contentType +/// * responseCode +/// * body +/// * headers (an object) +/// +/// FoxxApplication adds the following methods to this response object. +//////////////////////////////////////////////////////////////////////////////// + responseFunctions = { - // ### The straightforward `status` function - // Set the status code of your response, for example: - // - // response.status(404); +//////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_foxx_BaseMiddleware_response_status +/// @brief The straightforward `status` function +/// +/// Set the status code of your response, for example: +/// +/// @EXAMPLES +/// response.status(404); +//////////////////////////////////////////////////////////////////////////////// status: function (code) { this.responseCode = code; }, - // ### The radical `set` function - // Set a header attribute, for example: - // - // response.set("Content-Length", 123); - // response.set("Content-Type", "text/plain"); - // - // or alternatively: - // - // response.set({ - // "Content-Length": "123", - // "Content-Type": "text/plain" - // }); +//////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_foxx_BaseMiddleware_response_set +/// @brief The radical `set` function +/// +/// Set a header attribute, for example: +/// +/// @EXAMPLES +/// response.set("Content-Length", 123); +/// response.set("Content-Type", "text/plain"); +/// +/// or alternatively: +/// +/// @EXAMPLES +/// response.set({ +/// "Content-Length": "123", +/// "Content-Type": "text/plain" +/// }); +//////////////////////////////////////////////////////////////////////////////// set: function (key, value) { var attributes = {}; if (_.isUndefined(value)) { @@ -412,46 +510,57 @@ BaseMiddleware = function (templateCollection, helperCollection) { }, this); }, - // ### The magical `json` function - // Set the content type to JSON and the body to the - // JSON encoded object you provided. - // - // response.json({'born': 'December 12, 1915'}); +//////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_foxx_BaseMiddleware_response_json +/// @brief The magical `json` function +/// +/// 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) { this.contentType = "application/json"; this.body = JSON.stringify(obj); }, - // ### The mysterious `render` function - // If you initialize your FoxxApplication with a `templateCollection`, - // you're in luck now. - // It expects documents in the following form in this collection: - // - // { - // path: "high/way", - // content: "hallo <%= username %>", - // contentType: "text/plain", - // templateLanguage: "underscore" - // } - // - // The `content` is the string that will be rendered by the template - // processor. The `contentType` is the type of content that results - // from this call. And with the `templateLanguage` you can choose - // your template processor. There is only one choice now: `underscore`. - // - // If you call render, FoxxApplication will look - // into the this collection and search by the path attribute. - // It will then render the template with the given data: - // - // response.render("high/way", {username: 'FoxxApplication'}) - // - // Which would set the body of the response to `hello FoxxApplication` with the - // 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. +//////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_foxx_BaseMiddleware_response_render +/// @brief The mysterious `render` function +/// +/// If you initialize your FoxxApplication with a `templateCollection`, +/// you're in luck now. +/// It expects documents in the following form in this collection: +/// +/// @EXAMPLES +/// { +/// path: "high/way", +/// content: "hallo <%= username %>", +/// contentType: "text/plain", +/// templateLanguage: "underscore" +/// } +/// +/// The `content` is the string that will be rendered by the template +/// processor. The `contentType` is the type of content that results +/// from this call. And with the `templateLanguage` you can choose +/// your template processor. There is only one choice now: `underscore`. +/// +/// If you call render, FoxxApplication will look +/// into the this collection and search by the path attribute. +/// It will then render the template with the given data: +/// +/// @EXAMPLES +/// response.render("high/way", {username: 'FoxxApplication'}) +/// +/// Which would set the body of the response to `hello FoxxApplication` with the +/// 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) { var template; @@ -474,9 +583,9 @@ BaseMiddleware = function (templateCollection, helperCollection) { } }; - // Now enhance the request and response as described above and call next at the - // end of this middleware (otherwise your application would never - // be executed. Would be a shame, really). +/// Now enhance the request and response as described above and call next at the +/// end of this middleware (otherwise your application would never +/// be executed. Would be a shame, really). request = _.extend(request, requestFunctions); response = _.extend(response, responseFunctions); next(); @@ -488,32 +597,37 @@ BaseMiddleware = function (templateCollection, helperCollection) { }; }; -// ## The Format Middleware -// Unlike the `BaseMiddleware` this Middleware is only loaded if you -// want it. This Middleware gives you Rails-like format handling via -// the `extension` of the URL or the accept header. -// Say you request an URL like `/people.json`: -// The `FormatMiddleware` will set the format of the request to JSON -// and then delete the `.json` from the request. You can therefore write -// handlers that do not take an `extension` into consideration and instead -// handle the format via a simple String. -// To determine the format of the request it checks the URL and then -// 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, -// an error is raised. -// -// Use it by calling: -// -// FormatMiddleware = require('foxx').FormatMiddleware; -// app.before("/*", FormatMiddleware.new(['json'])); -// -// or the shortcut: -// -// 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. +//////////////////////////////////////////////////////////////////////////////// +/// @brief The Format Middleware +/// +/// Unlike the `BaseMiddleware` this Middleware is only loaded if you +/// want it. This Middleware gives you Rails-like format handling via +/// the `extension` of the URL or the accept header. +/// Say you request an URL like `/people.json`: +/// The `FormatMiddleware` will set the format of the request to JSON +/// and then delete the `.json` from the request. You can therefore write +/// handlers that do not take an `extension` into consideration and instead +/// handle the format via a simple String. +/// To determine the format of the request it checks the URL and then +/// 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, +/// an error is raised. +/// +/// Use it by calling: +/// +/// @EXAMPLES +/// FormatMiddleware = require('foxx').FormatMiddleware; +/// app.before("/*", FormatMiddleware.new(['json'])); +/// +/// or the shortcut: +/// +/// @EXAMPLES +/// 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) { 'use strict'; 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. -// Everything else will remain our secret. +/// We finish off with exporting FoxxApplication and the middlewares. +/// Everything else will remain our secret. //////////////////////////////////////////////////////////////////////////////// /// @brief loads a manifest file @@ -654,11 +768,15 @@ exports.FoxxApplication = FoxxApplication; exports.BaseMiddleware = BaseMiddleware; exports.FormatMiddleware = FormatMiddleware; -// ----------------------------------------------------------------------------- -// --SECTION-- END-OF-FILE -// ----------------------------------------------------------------------------- +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// -// Local Variables: -// mode: outline-minor -// outline-regexp: "/// @brief\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}\\|/\\*jslint" -// End: +/// ----------------------------------------------------------------------------- +/// --SECTION-- END-OF-FILE +/// ----------------------------------------------------------------------------- + +/// Local Variables: +/// mode: outline-minor +/// outline-regexp: "/// @brief\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}\\|/\\*jslint" +/// End: