Merge: Check binary files that might be wrongly commited
[nit.git] / lib / popcorn / README.md
index 08f7c9a..bbc9c95 100644 (file)
@@ -175,6 +175,17 @@ directory from where you launch your app.
 If you run the app from another directory, it’s safer to use the absolute path of
 the directory that you want to serve.
 
+In some cases, you can want to redirect request to static files to a default file
+instead of returning a 404 error.
+This can be achieved by specifying a default file in the StaticHandler:
+
+~~~
+app.use("/static/", new StaticHandler("public/", "default.html"))
+~~~
+
+This way all non-matched queries to the StaticHandler will be answered with the
+`default.html` file.
+
 ## Advanced Routing
 
 **Routing** refers to the definition of application end points (URIs) and how
@@ -353,7 +364,7 @@ The app declared in this example will try to match the routes in this order:
 ### Route parameters
 
 **Route parameters** are variable parts of a route path. They can be used to path
-arguments within the URI.\13
+arguments within the URI.
 Parameters in a route are prefixed with a colon `:` like in `:userId`, `:year`.
 
 The following example declares a handler `UserHome` that responds with the `user`
@@ -428,6 +439,23 @@ receive a `404 Not found` error.
 * `res.send()` Send a response of various types.
 * `res.error()` Set the response status code and send its message as the response body.
 
+## Response cycle
+
+When the popcorn `App` receives a request, the response cycle is the following:
+
+1. `pre-middlewares` lookup matching middlewares registered with `use_before(pre_middleware)`:
+       1. execute matching middleware by registration order
+       2. if a middleware send a response then let the `pre-middlewares` loop continue
+          with the next middleware
+2. `response-handlers` lookup matching handlers registered with `use(handler)`:
+       1. execute matching middleware by registration order
+       2. if a middleware send a response then stop the `response-handlers` loop
+       3. if no hander matches or sends a response, generate a 404 response
+3. `post-middlewares` lookup matching handlers registered with `use_after(post_handler)`:
+       1. execute matching middleware by registration order
+       2. if a middleware send a response then let the `post-middlewares` loop continue
+          with the next middleware
+
 ## Middlewares
 
 ### Overview
@@ -465,7 +493,7 @@ end
 
 
 var app = new App
-app.use("/*", new MyLogger)
+app.use_before("/*", new MyLogger)
 app.use("/", new HelloHandler)
 app.listen("localhost", 3000)
 ~~~
@@ -474,8 +502,9 @@ By using the `MyLogger` handler to the route `/*` we ensure that every requests
 (even 404 ones) pass through the middleware handler.
 This handler just prints “Request Logged!” when a request is received.
 
-The order of middleware loading is important: middleware functions that are loaded first are also executed first.
-In the above example, `MyLogger` will be executed before `HelloHandler`.
+Be default, the order of middleware execution is that are loaded first are also executed first.
+To ensure our middleware `MyLogger` will be executed before all the other, we add it
+with the `use_before` method.
 
 ### Ultra cool, more advanced logger example
 
@@ -505,7 +534,7 @@ class LogHandler
        redef fun all(req, res) do
                var timer = req.timer
                if timer != null then
-                       print "{req.method} {req.uri} {res.color_status} ({timer.total})"
+                       print "{req.method} {req.uri} {res.color_status} ({timer.total}s)"
                else
                        print "{req.method} {req.uri} {res.color_status}"
                end
@@ -519,9 +548,9 @@ class HelloHandler
 end
 
 var app = new App
-app.use("/*", new RequestTimeHandler)
+app.use_before("/*", new RequestTimeHandler)
 app.use("/", new HelloHandler)
-app.use("/*", new LogHandler)
+app.use_after("/*", new LogHandler)
 app.listen("localhost", 3000)
 ~~~
 
@@ -530,9 +559,15 @@ Doing so we can access our data from all handlers that import our module, direct
 from the `req` parameter.
 
 We use the new middleware called `RequestTimeHandler` to initialize the request timer.
+Because of the `use_before` method, the `RequestTimeHandler` middleware will be executed
+before all the others.
+
+We then let the `HelloHandler` produce the response.
 
 Finally, our `LogHandler` will display a bunch of data and use the request `timer`
 to display the time it took to process the request.
+Because of the `use_after` method, the `LogHandler` middleware will be executed after
+all the others.
 
 The app now uses the `RequestTimeHandler` middleware for every requests received
 by the Popcorn app.
@@ -683,7 +718,7 @@ app.listen("localhost", 3000)
 
 ## Sessions
 
-**Sessions** can be used thanks to the built-in `SessionMiddleware`.
+**Sessions** can be used thanks to the built-in `SessionInit` middleware.
 
 Here a simple example of login button that define a value in the `req` session.
 
@@ -712,7 +747,7 @@ class AppLogin
 end
 
 var app = new App
-app.use("/*", new SessionInit)
+app.use_before("/*", new SessionInit)
 app.use("/", new AppLogin)
 app.listen("localhost", 3000)
 ~~~
@@ -808,8 +843,13 @@ to your angular controller:
 import popcorn
 
 var app = new App
-app.use("/*", new StaticHandler("my-ng-app/"))
+app.use("/*", new StaticHandler("my-ng-app/", "index.html"))
 app.listen("localhost", 3000)
 ~~~
 
+Because the StaticHandler will not find the angular routes as static files,
+you must specify the path to the default angular controller.
+In this example, the StaticHandler will redirect any unknown requests to the `index.html`
+angular controller.
+
 See the examples for a more detailed use case working with a JSON API.