diff --git a/docs/application.rst b/docs/application.rst
index 6d407220b..7b0f4c3b4 100644
--- a/docs/application.rst
+++ b/docs/application.rst
@@ -38,7 +38,7 @@ a :doc:`route` instance.
.. code:: vala
- app.get ("", (req, res, next, stack) => {
+ app.get ("", (req, res, next, context) => {
res.body.write_all ("Hello world!".data, null);
});
@@ -48,7 +48,7 @@ processing. The callback, named handler, receives four arguments:
- a :doc:`vsgi/request` that describes a resource being requested
- a :doc:`vsgi/response` that correspond to that resource
- a ``next`` continuation to `keep routing`
-- a routing ``stack`` to retrieve and store states from previous and for
+- a routing ``context`` to retrieve and store states from previous and for
following handlers
Serving the application
diff --git a/docs/redirection-and-error.rst b/docs/redirection-and-error.rst
index f5b5bca55..e08815a1c 100644
--- a/docs/redirection-and-error.rst
+++ b/docs/redirection-and-error.rst
@@ -130,11 +130,11 @@ the :doc:`router` can handle them properly.
throw new ClientError.NOT_FOUND ("");
});
-During status handling, the error message will be pushed on the routing stack
-as a ``string``.
+During status handling, the error message will be pushed on the routing context
+as a ``string`` to the key ``message``.
.. code:: vala
- app.status (404, (req, res, next, stack) => {
- var message = stack.pop_tail ().get_string ();
+ app.status (404, (req, res, next, context) => {
+ var message = context["message"].get_string ();
});
diff --git a/docs/router.rst b/docs/router.rst
index d4da378bb..7f321047c 100644
--- a/docs/router.rst
+++ b/docs/router.rst
@@ -25,29 +25,21 @@ It can be performed automatically with ``Router.use``:
next (req, res);
});
-Routing stack
--------------
+Routing context
+---------------
During the routing, states can obtained from a previous handler or passed to
-the next one using the routing stack. The stack is a simple `GLib.Queue`_ that
-can be accessed from its head or tail.
-
-.. warning::
-
- The queue tail is used to perform stack operations with ``push_tail`` and
- ``pop_tail``.
-
-.. _GLib.Queue: http://valadoc.org/#!api=glib-2.0/GLib.Queue
+the next one using the routing context.
.. code:: vala
- app.get ("", (req, res, next, stack) => {
- stack.push_tail ("some value");
+ app.get ("", (req, res, next, context) => {
+ context["some key"] = "some value";
next (req, res);
});
- app.get ("", (req, res, next, stack) => {
- var some_value = stack.pop_tail ().get_string ();
+ app.get ("", (req, res, next, context) => {
+ var some_value = context["some key"]; // or context.parent["some key"]
});
HTTP methods
@@ -151,14 +143,14 @@ Thrown status code can be handled by a ``HandlerCallback`` pretty much like how
typically matched requests are being handled.
The received :doc:`vsgi/request` and :doc:`vsgi/response` object are in the
-same state they were when the status was thrown. The error message is stacked
-and available in the ``HandlerCallback`` last parameter.
+same state they were when the status was thrown. The error message is bound to
+the key ``message`` in the routing context.
.. code:: vala
- app.status (Soup.Status.NOT_FOUND, (req, res, next, stack) => {
+ app.status (Soup.Status.NOT_FOUND, (req, res, next, context) => {
// produce a 404 page...
- var message = stack.pop_tail ().get_string ();
+ var message = context["message"].get_string ();
});
Similarly to conventional request handling, the ``next`` continuation can be
@@ -257,7 +249,7 @@ application.
a maximum inter-operability with other frameworks based on VSGI.
The following example delegates all ``GET`` requests to another router which
-will process in isolation with its own routing stack.
+will process in isolation with its own routing context.
.. code:: vala
@@ -301,25 +293,6 @@ Filters
// res is transparently gzipped
})
-Stacked states
-~~~~~~~~~~~~~~
-
-Additionally, states can be passed to the next handler in the queue by pushing
-them in a stack.
-
-.. code:: vala
-
- app.get ("", (req, res, next, stack) => {
- message ("pre");
- stack.push_tail (new Object ()); // propagate the state
- next (req, res);
- });
-
- app.get ("", (req, res, next, stack) => {
- // perform an operation with the provided state
- var obj = stack.pop_tail ();
- });
-
Sequence
--------
@@ -386,8 +359,8 @@ responses designed for non-human client.
});
});
- app.status (Status.NOT_ACCEPTABLE, (req, res, next, stack) => {
- res.body.write_all ("
%s
".printf (stack.pop_tail ().get_string ()).data, null);
+ app.status (Status.NOT_ACCEPTABLE, (req, res, next, context) => {
+ res.body.write_all ("%s
".printf (context["message"].get_string ()).data, null);
});
Middleware
@@ -482,8 +455,8 @@ attached to a :doc:`route`, the processing will happen in a ``NextCallback``.
.. code:: vala
- app.get ("home", (req, res, next, stack) => {
+ app.get ("home", (req, res, next, context) => {
compress (req, res, (req, res) => {
res.body.write_all ("Hello world!".data, null);
- }, stack);
+ }, new Context.with_parent (context));
});
diff --git a/examples/app/app.vala b/examples/app/app.vala
index 74f75bb37..b254013a3 100644
--- a/examples/app/app.vala
+++ b/examples/app/app.vala
@@ -82,14 +82,14 @@ app.get ("cookies", (req, res) => {
});
app.scope ("cookie", (inner) => {
- inner.get ("", (req, res) => {
+ inner.get ("", (req, res, next, context) => {
foreach (var cookie in VSGI.Cookies.from_request (req))
- if (cookie.name == req.params["name"])
+ if (cookie.name == context["name"].get_string ())
res.body.write_all ("%s\n".printf (cookie.value).data, null);
});
- inner.post ("", (req, res) => {
- var cookie = new Soup.Cookie (req.params["name"], req.flatten_utf8 (), "0.0.0.0", "/", 60);
+ inner.post ("", (req, res, next, context) => {
+ var cookie = new Soup.Cookie (context["name"].get_string (), req.flatten_utf8 (), "0.0.0.0", "/", 60);
res.headers.append ("Set-Cookie", cookie.to_set_cookie_header ());
});
});
@@ -140,13 +140,13 @@ app.method (VSGI.Request.GET, "custom-method", (req, res) => {
res.body.write_all (req.method.data, null);
});
-app.get ("hello/", (req, res) => {
- res.body.write_all ("hello %s!".printf (req.params["id"]).data, null);
+app.get ("hello/", (req, res, next, context) => {
+ res.body.write_all ("hello %s!".printf (context["id"].get_string ()).data, null);
});
-app.get ("users//", (req, res) => {
- var id = req.params["id"];
- var test = req.params["action"];
+app.get ("users//", (req, res, next, context) => {
+ var id = context["id"].get_string ();
+ var test = context["action"].get_string ();
var writer = new DataOutputStream (res.body);
writer.put_string (@"id\t=> $id\n");
@@ -155,8 +155,8 @@ app.get ("users//", (req, res) => {
app.types["permutations"] = /abc|acb|bac|bca|cab|cba/;
-app.get ("custom-route-type/", (req, res) => {
- res.body.write_all (req.params["p"].data, null);
+app.get ("custom-route-type/", (req, res, next, context) => {
+ res.body.write_all (context["p"].get_string ().data, null);
});
app.regex (VSGI.Request.GET, /custom-regular-expression/, (req, res) => {
@@ -193,8 +193,8 @@ app.get ("not-found", (req, res) => {
var api = new Router ();
-api.get ("repository/", (req, res) => {
- var name = req.params["name"];
+api.get ("repository/", (req, res, next, context) => {
+ var name = context["name"].get_string ();
res.body.write_all (name.data, null);
});
@@ -209,17 +209,17 @@ app.get ("next", (req, res) => {
res.body.write_all ("Matched by the next route in the queue.".data, null);
});
-app.get ("state", (req, res, next, stack) => {
- stack.push_tail ("I have been passed!");
+app.get ("state", (req, res, next, context) => {
+ context["state"] = "I have been passed!";
next (req, res);
});
-app.get ("state", (req, res, next, stack) => {
- res.body.write_all (stack.pop_tail ().get_string ().data, null);
+app.get ("state", (req, res, next, context) => {
+ res.body.write_all (context["state"].get_string ().data, null);
});
// Ctpl template rendering
-app.get ("ctpl//", (req, res) => {
+app.get ("ctpl//", (req, res, next, context) => {
var tpl = new View.from_string ("""
hello {foo}
hello {bar}
@@ -230,8 +230,8 @@ app.get ("ctpl//", (req, res) => {
""");
- tpl.push_string ("foo", req.params["foo"]);
- tpl.push_string ("bar", req.params["bar"]);
+ tpl.push_string ("foo", context["foo"].get_string ());
+ tpl.push_string ("bar", context["bar"].get_string ());
tpl.push_strings ("strings", {"a", "b", "c"});
tpl.push_int ("int", 1);
@@ -240,9 +240,9 @@ app.get ("ctpl//", (req, res) => {
});
// serve static resource using a path route parameter
-app.get ("static/.", (req, res) => {
- var resource = req.params["resource"];
- var type = req.params["type"];
+app.get ("static/.", (req, res, next, context) => {
+ var resource = context["resource"].get_string ();
+ var type = context["type"].get_string ();
var path = "/static/%s.%s".printf (resource, type);
bool uncertain;
@@ -279,9 +279,9 @@ app.get ("server-sent-events", stream_events ((req, send) => {
});
}));
-app.status (Soup.Status.NOT_FOUND, (req, res, next, stack) => {
+app.status (Soup.Status.NOT_FOUND, (req, res, next, context) => {
var template = new View.from_stream (resources_open_stream ("/templates/404.html", ResourceLookupFlags.NONE));
- template.environment.push_string ("message", stack.pop_tail ().get_string ());
+ template.environment.push_string ("message", context["message"].get_string ());
res.status = Soup.Status.NOT_FOUND;
HashTable @params;
res.headers.get_content_type (out @params);
diff --git a/examples/fastcgi/app.vala b/examples/fastcgi/app.vala
index 27b43f020..1399d7d6b 100644
--- a/examples/fastcgi/app.vala
+++ b/examples/fastcgi/app.vala
@@ -26,8 +26,8 @@ public static int main (string[] args) {
res.body.write_all ("Hello world!".data, null);
});
- app.get ("random/", (req, res) => {
- var size = int.parse (req.params["size"]);
+ app.get ("random/", (req, res, next, context) => {
+ var size = int.parse (context["size"].get_string ());
var writer = new DataOutputStream (res.body);
for (; size > 0; size--) {
diff --git a/examples/memcached/app.vala b/examples/memcached/app.vala
index 70d42865a..acd7a1e5a 100644
--- a/examples/memcached/app.vala
+++ b/examples/memcached/app.vala
@@ -21,8 +21,8 @@ using VSGI.Soup;
var app = new Router ();
var memcached = new Memcached.Context.from_configuration ("--SERVER=localhost".data);
-app.get ("", (req, res, next, stack) => {
- var key = stack.pop_tail ().get_string ();
+app.get ("", (req, res, next, context) => {
+ var key = context["key"].get_string ();
uint32 flags;
Memcached.ReturnCode error;
@@ -39,8 +39,8 @@ app.get ("", (req, res, next, stack) => {
}
});
-app.put ("", (req, res, next, stack) => {
- var key = stack.pop_tail ().get_string ();
+app.put ("", (req, res, next, context) => {
+ var key = context["key"].get_string ();
var buffer = new MemoryOutputStream (null, realloc, free);
@@ -59,8 +59,8 @@ app.put ("", (req, res, next, stack) => {
}
});
-app.delete ("", (req, res, next, stack) => {
- var key = stack.pop_tail ().get_string ();
+app.delete ("", (req, res, next, context) => {
+ var key = context["key"].get_string ();
var error = memcached.delete (key.data, 0);
diff --git a/examples/scgi/app.vala b/examples/scgi/app.vala
index c0e8ef5cc..149ec989e 100644
--- a/examples/scgi/app.vala
+++ b/examples/scgi/app.vala
@@ -32,4 +32,4 @@ app.get ("async", (req, res) => {
res.body.write_all_async.begin ("Hello world!".data, Priority.DEFAULT, null);
});
-new Server ("org.valum.example.SCGI", app.handle).run ();
+new Server ("org.valum.example.SCGI", app.handle).run ({"app", "--port", "3003"});
diff --git a/src/valum-context.vala b/src/valum-context.vala
new file mode 100644
index 000000000..d54f97468
--- /dev/null
+++ b/src/valum-context.vala
@@ -0,0 +1,83 @@
+/*
+ * This file is part of Valum.
+ *
+ * Valum is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Valum is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Valum. If not, see .
+ */
+
+using GLib;
+
+/**
+ * Routing context that stores various states for middleware interaction.
+ *
+ * @since 0.3
+ */
+public class Valum.Context : Object {
+
+ /**
+ * Internal mapping of states.
+ */
+ private HashTable states = new HashTable (str_hash, str_equal);
+
+ /**
+ * Parent's context from which missing keys are resolved.
+ *
+ * @since 0.3
+ */
+ public Context? parent { construct; get; default = null; }
+
+ /**
+ * Create a new root context.
+ *
+ * @since 0.3
+ */
+ public Context () {
+
+ }
+
+ /**
+ * Create a new child context.
+ *
+ * @since 0.3
+ */
+ public Context.with_parent (Context parent) {
+ Object (parent: parent);
+ }
+
+ /**
+ * Obtain a key from this context or its parent if it's not found.
+ *
+ * @since 0.3
+ */
+ public new Value? @get (string key) {
+ return states[key] ?? (parent == null ? null : parent[key]);
+ }
+
+ /**
+ * Set a key in this context.
+ *
+ * @since 0.3
+ */
+ public new void @set (string key, Value? @value) {
+ states[key] = @value;
+ }
+
+ /**
+ * Lookup if this context or its parent has a key.
+ *
+ * @since 0.3
+ */
+ public bool contains (string key) {
+ return states.contains (key) || (parent != null && parent.contains (key));
+ }
+}
diff --git a/src/valum-route.vala b/src/valum-route.vala
index c5d2363f4..cc3d128e2 100644
--- a/src/valum-route.vala
+++ b/src/valum-route.vala
@@ -106,17 +106,14 @@ namespace Valum {
// regex are optimized automatically :)
var prepared_regex = new Regex (pattern.str, RegexCompileFlags.OPTIMIZE);
- this (router, method, (req, stack) => {
+ this (router, method, (req, context) => {
MatchInfo match_info;
if (prepared_regex.match (req.uri.get_path (), 0, out match_info)) {
if (captures.length () > 0) {
- // populate the request parameters
- var p = new HashTable (str_hash, str_equal);
+ // populate the context parameters
foreach (var capture in captures) {
- p[capture] = match_info.fetch_named (capture);
- stack.push_tail (match_info.fetch_named (capture));
+ context[capture] = match_info.fetch_named (capture);
}
- req.params = p;
}
return true;
}
@@ -190,7 +187,7 @@ namespace Valum {
public Route then (owned HandlerCallback handler) {
return this.router.matcher (this.method, (req, stack) => {
// since the same matcher is shared, we preserve the stack intact
- return match (req, new Queue ());
+ return match (req, new Context ());
}, (owned) handler);
}
}
diff --git a/src/valum-router.vala b/src/valum-router.vala
index 7d7ddb42e..780c0c4e0 100644
--- a/src/valum-router.vala
+++ b/src/valum-router.vala
@@ -272,26 +272,23 @@ namespace Valum {
private bool perform_routing (List routes,
Request req,
Response res,
- Queue stack) throws Informational,
+ Context context) throws Informational,
Success,
Redirection,
ClientError,
ServerError,
Error {
- var tmp_stack = new Queue ();
for (unowned List node = routes; node != null; node = node.next) {
- tmp_stack.clear ();
- if ((node.data.method == null || node.data.method == req.method) && node.data.match (req, tmp_stack)) {
- // commit the stack pushes
- while (!tmp_stack.is_empty ())
- stack.push_tail (tmp_stack.pop_head ());
+ var local_context = new Context.with_parent (context);
+ if ((node.data.method == null || node.data.method == req.method) &&
+ node.data.match (req, local_context)) {
node.data.fire (req, res, (req, res) => {
// keep routing if there are more routes to explore
if (node.next != null)
- if (perform_routing (node.next, req, res, stack))
+ if (perform_routing (node.next, req, res, local_context))
return;
throw new ClientError.NOT_FOUND ("The request URI %s was not found.", req.uri.to_string (true));
- }, stack);
+ }, local_context);
return true;
}
}
@@ -322,15 +319,15 @@ namespace Valum {
err is ServerError) ? err.code : 500;
/*
- * Only the error message is pushed on the stack, the handler
- * should assume that the status code is the one for which it
- * has been registered.
+ * Only the error message is pushed on the routing context, the
+ * handler should assume that the status code is the one for
+ * which it has been registered.
*/
if (this.status_handlers.contains (status_code)) {
- var stack = new Queue ();
- stack.push_tail (err.message);
+ var context = new Context ();
+ context["message"] = err.message;
try {
- if (this.perform_routing (this.status_handlers[status_code].head, req, res, stack))
+ if (this.perform_routing (this.status_handlers[status_code].head, req, res, context))
return; // handled!
} catch (Error err) {
// feed the error back in the invocation
@@ -444,10 +441,10 @@ namespace Valum {
// initial invocation
this.invoke (req, res, () => {
- var stack = new Queue ();
+ var context = new Context ();
// ensure at least one route has been declared with that method
- if (this.perform_routing (this.routes.head, req, res, stack))
+ if (this.perform_routing (this.routes.head, req, res, context))
return; // something matched
// find routes from other methods matching this request
@@ -460,7 +457,7 @@ namespace Valum {
#else
!string.joinv (",", allowed).contains (route.method) &&
#endif
- route.match (req, stack)) {
+ route.match (req, new Context ())) {
allowed += route.method;
}
}
diff --git a/src/valum-server-sent-events.vala b/src/valum-server-sent-events.vala
index 1abc227f2..4c3062152 100644
--- a/src/valum-server-sent-events.vala
+++ b/src/valum-server-sent-events.vala
@@ -56,13 +56,13 @@ namespace Valum.ServerSentEvents {
*
* @param request request this is responding to
* @param send_event send a SSE message
- * @param stack
+ * @param context
*
* @throws GLib.Error
*/
public delegate void EventStreamCallback (Request request,
owned SendEventCallback send_event,
- Queue stack) throws Error;
+ Context context) throws Error;
/**
* Middleware that create a context for sending Server-Sent Events.
@@ -83,7 +83,7 @@ namespace Valum.ServerSentEvents {
* @param context context for sending events
*/
public HandlerCallback stream_events (owned EventStreamCallback context) {
- return (req, res, next, stack) => {
+ return (req, res, next, _context) => {
HashTable @params;
res.headers.get_content_type (out @params);
res.headers.set_content_type ("text/event-stream", @params);
@@ -111,7 +111,7 @@ namespace Valum.ServerSentEvents {
res.body.write_all (message.str.data, null);
res.body.flush ();
- }, stack);
+ }, _context);
} catch (Error err) {
warning (err.message);
}
diff --git a/src/valum.vala b/src/valum.vala
index 9f8636b08..2c0216a02 100644
--- a/src/valum.vala
+++ b/src/valum.vala
@@ -35,17 +35,14 @@ namespace Valum {
public delegate void LoaderCallback (Router router);
/**
- * Match the request and populate the {@link VSGI.Request.params}.
- *
- * It is important for a matcher to populate the
- * {@link VSGI.Request.params} only if it matches the request.
+ * Match the request and populate the initial {@link Valum.Context}.
*
* @since 0.1
*
- * @param req request being matched
- * @param initial_stack destination for the initial routing stack
+ * @param req request being matched
+ * @param context initial context
*/
- public delegate bool MatcherCallback (Request req, Queue initial_stack);
+ public delegate bool MatcherCallback (Request req, Context context);
/**
* Produce a matching middleware that negates the provided middleware.
@@ -91,21 +88,22 @@ namespace Valum {
* @throws ServerError trigger a 5xx server error
* @throws Error any other error which will be handled as a {@link Valum.ServerError.INTERNAL}
*
- * @param req request being handled
- * @param res response to send back to the requester
- * @param next keep routing
- * @param stack routing stack as altered by the preceeding next invocation
- * or initialized by the first {@link Valum.MatcherCallback}
+ * @param req request being handled
+ * @param res response to send back to the requester
+ * @param next keep routing
+ * @param context routing context which parent is the context of the
+ * preceeding 'next' invocation or initialized by the
+ * first {@link Valum.MatcherCallback}
*/
public delegate void HandlerCallback (Request req,
Response res,
NextCallback next,
- Queue stack) throws Informational,
- Success,
- Redirection,
- ClientError,
- ServerError,
- Error;
+ Context context) throws Informational,
+ Success,
+ Redirection,
+ ClientError,
+ ServerError,
+ Error;
/**
* Continuation passed in a {@link Valum.HandlerCallback} to *keep routing*
diff --git a/src/vsgi-request.vala b/src/vsgi-request.vala
index ecdda5742..b05d99597 100644
--- a/src/vsgi-request.vala
+++ b/src/vsgi-request.vala
@@ -61,16 +61,6 @@ namespace VSGI {
*/
public const string[] METHODS = {OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT, PATCH};
- /**
- * Parameters for the request.
- *
- * These should be extracted from the URI path.
- *
- * @since 0.0.1
- */
- [Deprecated (since = "0.2")]
- public HashTable? @params { get; set; default = null; }
-
/**
* Connection containing raw streams.
*
diff --git a/tests/cgi-test.vala b/tests/cgi-test.vala
index 071afc48c..7bc098efb 100644
--- a/tests/cgi-test.vala
+++ b/tests/cgi-test.vala
@@ -43,7 +43,6 @@ public static void test_vsgi_cgi_request () {
assert (request.query.contains ("a"));
assert ("b" == request.query["a"]);
assert (3003 == request.uri.get_port ());
- assert (null == request.params);
assert ("example.com" == request.headers.get_one ("Host"));
assert (connection.input_stream == request.body);
}
diff --git a/tests/fastcgi-test.vala b/tests/fastcgi-test.vala
index 183817ea5..04b2ab798 100644
--- a/tests/fastcgi-test.vala
+++ b/tests/fastcgi-test.vala
@@ -38,7 +38,6 @@ public static void test_vsgi_fastcgi_request () {
assert ("0.0.0.0" == request.uri.get_host ());
assert (3003 == request.uri.get_port ());
assert (null == request.query);
- assert (null == request.params);
assert ("example.com" == request.headers.get_one ("Host"));
assert (connection.input_stream == request.body);
}
diff --git a/tests/negociate-test.vala b/tests/negociate-test.vala
index bfe5b2f0f..860eccfcf 100644
--- a/tests/negociate-test.vala
+++ b/tests/negociate-test.vala
@@ -9,9 +9,9 @@ public void test_negociate () {
req.headers.append ("Accept", "text/html; q=0.9, text/xml; q=0");
- assert (negociate ("Accept", "text/html") (req, null));
- assert (!negociate ("Accept", "text/xml") (req, null));
- assert (!negociate ("Accept-Encoding", "utf-8") (req, null));
+ assert (negociate ("Accept", "text/html") (req, new Context ()));
+ assert (!negociate ("Accept", "text/xml") (req, new Context ()));
+ assert (!negociate ("Accept-Encoding", "utf-8") (req, new Context ()));
}
diff --git a/tests/route-test.vala b/tests/route-test.vala
index 1b517b0cf..acfbc7f91 100644
--- a/tests/route-test.vala
+++ b/tests/route-test.vala
@@ -22,12 +22,12 @@ using VSGI.Test;
* @since 0.1
*/
public void test_route () {
- var router = new Router ();
- var route = new Route (router, "GET", (req) => { return true; }, (req, res) => {});
- var req = new Request.with_uri (new Soup.URI ("http://localhost/5"));
- var stack = new Queue ();
+ var router = new Router ();
+ var route = new Route (router, "GET", (req) => { return true; }, (req, res) => {});
+ var req = new Request.with_uri (new Soup.URI ("http://localhost/5"));
+ var context = new Context ();
- assert (route.match (req, stack));
+ assert (route.match (req, context));
assert (router == route.router);
}
@@ -35,75 +35,64 @@ public void test_route () {
* @since 0.1
*/
public void test_route_from_rule () {
- var route = new Route.from_rule (new Router (), "GET", "", (req, res) => {});
+ var route = new Route.from_rule (new Router (), "GET", "", (req, res) => {});
var request = new Request.with_uri (new Soup.URI ("http://localhost/5"));
- var stack = new Queue ();
+ var context = new Context ();
- assert (route.match (request, stack));
- assert (request.params != null);
- assert (request.params["id"] == "5");
- assert ("5" == stack.pop_tail ().get_string ());
+ assert (route.match (request, context));
+ assert ("5" == context["id"].get_string ());
}
/**
* @since 0.1
*/
public void test_route_from_rule_null () {
- var route = new Route.from_rule (new Router (), "GET", null, (req, res) => {});
+ var route = new Route.from_rule (new Router (), "GET", null, (req, res) => {});
var request = new Request.with_uri (new Soup.URI ("http://localhost/5"));
- var stack = new Queue ();
+ var context = new Context ();
- assert (route.match (request, stack));
- assert (request.params != null);
- assert (request.params.contains ("path"));
- assert ("5" == request.params["path"]);
- assert ("5" == stack.pop_tail ().get_string ());
+ assert (route.match (request, context));
+ assert (context.contains ("path"));
+ assert ("5" == context["path"].get_string ());
}
/**
* @since 0.1
*/
public static void test_route_from_rule_null_matches_empty_path () {
- var route = new Route.from_rule (new Router (), "GET", null, (req, res) => {});
+ var route = new Route.from_rule (new Router (), "GET", null, (req, res) => {});
var request = new Request.with_uri (new Soup.URI ("http://localhost/"));
- var stack = new Queue ();
+ var context = new Context ();
- assert (route.match (request, stack));
- assert ("" == request.params["path"]);
- assert ("" == stack.pop_tail ().get_string ());
+ assert (route.match (request, context));
+ assert ("" == context["path"].get_string ());
}
/**
* @since 0.1
*/
public void test_route_from_rule_any () {
- var route = new Route.from_rule (new Router (), "GET", "", (req, res) => {});
+ var route = new Route.from_rule (new Router (), "GET", "", (req, res) => {});
var request = new Request.with_uri (new Soup.URI ("http://localhost/5"));
- var stack = new Queue ();
+ var context = new Context ();
- assert (route.match (request, stack));
+ assert (route.match (request, context));
- assert (request.params != null);
- assert (request.params["id"] == "5");
- assert ("5" == stack.pop_tail ().get_string ());
+ assert ("5" == context["id"].get_string ());
}
/**
* @since 0.1
*/
public void test_route_from_rule_without_captures () {
- var route = new Route.from_rule (new Router (), "GET", "", (req, res) => {});
- var req = new Request.with_uri (new Soup.URI ("http://localhost/"));
- var stack = new Queue ();
-
- assert (req.params == null);
+ var route = new Route.from_rule (new Router (), "GET", "", (req, res) => {});
+ var req = new Request.with_uri (new Soup.URI ("http://localhost/"));
+ var context = new Context ();
- var matches = route.match (req, stack);
+ var matches = route.match (req, context);
// ensure params are still null if there is no captures
assert (matches);
- assert (req.params == null);
- assert (stack.is_empty ());
}
/**
@@ -117,43 +106,31 @@ public void test_route_from_rule_undefined_type () {
* @since 0.1
*/
public void test_route_from_regex () {
- var route = new Route.from_regex (new Router (), "GET", /(?\d+)/, (req, res) => {});
- var req = new Request.with_uri (new Soup.URI ("http://localhost/5"));
- var stack = new Queue ();
-
- assert (req.params == null);
+ var route = new Route.from_regex (new Router (), "GET", /(?\d+)/, (req, res) => {});
+ var req = new Request.with_uri (new Soup.URI ("http://localhost/5"));
+ var context = new Context ();
- var matches = route.match (req, stack);
+ var matches = route.match (req, context);
assert (matches);
- assert (req.params != null);
- assert (req.params["id"] == "5");
- assert ("5" == stack.pop_tail ().get_string ());
+ assert ("5" == context["id"].get_string ());
}
/**
* @since 0.2
*/
public void test_route_from_regex_multiple_captures () {
- var route = new Route.from_regex (new Router (), "GET", /(?\w+)\/(?\d+)/, (req, res) => {});
- var req = new Request.with_uri (new Soup.URI ("http://localhost/user/5"));
- var stack = new Queue ();
+ var route = new Route.from_regex (new Router (), "GET", /(?\w+)\/(?\d+)/, (req, res) => {});
+ var req = new Request.with_uri (new Soup.URI ("http://localhost/user/5"));
+ var context = new Context ();
- assert (req.params == null);
-
- var matches = route.match (req, stack);
-
- assert (matches);
- assert (req.params != null);
+ assert (route.match (req, context));
- assert ("action" in req.params);
- assert ("id" in req.params);
+ assert ("action" in context);
+ assert ("id" in context);
- assert ("user" == req.params["action"]);
- assert ("5" == req.params["id"]);
-
- assert ("5" == stack.pop_tail ().get_string ());
- assert ("user" == stack.pop_tail ().get_string ());
+ assert ("user" == context["action"].get_string ());
+ assert ("5" == context["id"].get_string ());
}
/**
@@ -164,66 +141,54 @@ public void test_route_from_regex_scoped () {
router.scopes.push_tail ("test");
- var route = new Route.from_regex (router, "GET", /(?\d+)/, (req, res) => {});
- var req = new Request.with_uri (new Soup.URI ("http://localhost/test/5"));
- var stack = new Queue ();
-
- assert (req.params == null);
+ var route = new Route.from_regex (router, "GET", /(?\d+)/, (req, res) => {});
+ var req = new Request.with_uri (new Soup.URI ("http://localhost/test/5"));
+ var context = new Context ();
- var matches = route.match (req, stack);
+ assert (route.match (req, context));
- assert (matches);
- assert (req.params != null);
- assert (req.params["id"] == "5");
- assert ("5" == stack.pop_tail ().get_string ());
+ assert ("5" == context["id"].get_string ());
}
/**
* @since 0.1
*/
public void test_route_from_regex_without_captures () {
- var route = new Route.from_regex (new Router (), "GET", /.*/, (req, res) => {});
- var req = new Request.with_uri (new Soup.URI ("http://localhost/"));
- var stack = new Queue ();
+ var route = new Route.from_regex (new Router (), "GET", /.*/, (req, res) => {});
+ var req = new Request.with_uri (new Soup.URI ("http://localhost/"));
+ var context = new Context ();
- var matches = route.match (req, stack);
+ var matches = route.match (req, context);
// ensure params are still null if there is no captures
- assert (route.match (req, stack));
- assert (req.params == null);
- assert (stack.is_empty ());
+ assert (route.match (req, context));
}
/**
* @since 0.1
*/
public void test_route_match () {
- var route = new Route.from_rule (new Router (), "GET", "", (req, res) => {});
- var req = new Request.with_uri (new Soup.URI ("http://localhost/5"));
- var stack = new Queue ();
+ var route = new Route.from_rule (new Router (), "GET", "", (req, res) => {});
+ var req = new Request.with_uri (new Soup.URI ("http://localhost/5"));
+ var context = new Context ();
- assert (req.params == null);
-
- var matches = route.match (req, stack);
+ var matches = route.match (req, context);
assert (matches);
- assert (req.params != null);
- assert (req.params.contains ("id"));
- assert ("5" == stack.pop_tail ().get_string ());
+ assert (context.contains ("id"));
+ assert ("5" == context["id"].get_string ());
}
/**
* @since 0.1
*/
public void test_route_match_not_matching () {
- var route = new Route.from_rule (new Router (), "GET", "", (req, res) => {});
- var req = new Request.with_uri (new Soup.URI ("http://localhost/home"));
- var stack = new Queue ();
+ var route = new Route.from_rule (new Router (), "GET", "", (req, res) => {});
+ var req = new Request.with_uri (new Soup.URI ("http://localhost/home"));
+ var context = new Context ();
// no match and params remains null
- assert (route.match (req, stack) == false);
- assert (req.params == null);
- assert (stack.is_empty ());
+ assert (route.match (req, context) == false);
}
/**
@@ -234,9 +199,10 @@ public void test_route_fire () {
var route = new Route.from_rule (new Router (), "GET", "", (req, res) => {
setted = true;
});
- var req = new Request.with_uri (new Soup.URI ("http://localhost/home"));
- var res = new Response (req);
- var stack = new Queue ();
+
+ var req = new Request.with_uri (new Soup.URI ("http://localhost/home"));
+ var res = new Response (req);
+ var context = new Context ();
assert (setted == false);
diff --git a/tests/router-test.vala b/tests/router-test.vala
index ec52444fb..59a7d4cab 100644
--- a/tests/router-test.vala
+++ b/tests/router-test.vala
@@ -660,8 +660,8 @@ public static void test_router_next_propagate_state () {
var router = new Router ();
var state = new Object ();
- router.get ("", (req, res, next, stack) => {
- stack.push_tail (state);
+ router.get ("", (req, res, next, context) => {
+ context["state"] = state;
next (req, res);
});
@@ -669,9 +669,9 @@ public static void test_router_next_propagate_state () {
next (req, res);
});
- router.get ("", (req, res, next, st) => {
+ router.get ("", (req, res, next, context) => {
res.status = 413;
- assert (st.pop_tail () == state);
+ assert (state == context["state"]);
});
var request = new Request.with_uri (new Soup.URI ("http://localhost/"));
@@ -689,19 +689,22 @@ public static void test_router_next_replace_propagated_state () {
var router = new Router ();
var state = new Object ();
- router.get ("", (req, res, next, stack) => {
- stack.push_tail (state);
+ router.get ("", (req, res, next, context) => {
+ context["state"] = state;
next (req, res);
});
- router.get ("", (req, res, next, stack) => {
- assert (state == stack.pop_tail ());
+ router.get ("", (req, res, next, context) => {
+ assert (state == context["state"]);
+ context["state"] = "something really different";
next (req, res);
});
- router.get ("", (req, res, next, stack) => {
+ router.get ("", (req, res, next, context) => {
res.status = 413;
- assert (stack.is_empty ());
+ assert (context["state"].holds (typeof (string)));
+ assert (context.parent["state"].holds (typeof (string)));
+ assert (context.parent.parent["state"].holds (typeof (Object)));
});
var request = new Request.with_uri (new Soup.URI ("http://localhost/"));
@@ -715,8 +718,8 @@ public static void test_router_next_replace_propagated_state () {
public static void test_router_status_propagates_error_message () {
var router = new Router ();
- router.status (404, (req, res, next, stack) => {
- var message = stack.pop_tail ();
+ router.status (404, (req, res, next, context) => {
+ var message = context["message"];
res.status = 418;
assert ("The request URI / was not found." == message.get_string ());
});
@@ -780,13 +783,13 @@ public static void test_router_invoke_propagate_state () {
var router = new Router ();
var message = "test";
- router.get ("", (req, res, next, stack) => {
- stack.push_tail (message);
+ router.get ("", (req, res, next, context) => {
+ context["message"] = message;
router.invoke (req, res, next);
});
- router.get ("", (req, res, next, stack) => {
- assert (message == stack.pop_tail ().get_string ());
+ router.get ("", (req, res, next, context) => {
+ assert (message == context["message"].get_string ());
throw new ClientError.IM_A_TEAPOT ("this is insane!");
});
@@ -827,18 +830,18 @@ public void test_router_then () {
/**
* @since 0.2.2
*/
-public void test_router_then_preserve_matching_stack () {
+public void test_router_then_preserve_matching_context () {
var router = new Router ();
var reached = false;
- router.get ("", (req, res, next, stack) => {
- stack.push_tail ("test");
+ router.get ("", (req, res, next, context) => {
+ context["test"] = "test";
next (req, res);
- }).then ((req, res, next, stack) => {
+ }).then ((req, res, next, context) => {
reached = true;
- assert ("test" == stack.pop_tail ().get_string ());
- assert ("5" == stack.pop_tail ().get_string ());
+ assert ("test" == context["test"].get_string ());
+ assert ("5" == context["id"].get_string ());
});
var req = new Request.with_uri (new Soup.URI ("http://localhost/5"));
diff --git a/tests/soup-test.vala b/tests/soup-test.vala
index 4251e40ee..0ac838f19 100644
--- a/tests/soup-test.vala
+++ b/tests/soup-test.vala
@@ -32,7 +32,6 @@ public static void test_vsgi_soup_request () {
assert ("0.0.0.0" == request.uri.get_host ());
assert (3003 == request.uri.get_port ());
assert (null == request.query);
- assert (null == request.params);
assert (message.request_headers == request.headers);
}
diff --git a/tests/tests.vala b/tests/tests.vala
index cd3f5c0d2..69c6e5924 100644
--- a/tests/tests.vala
+++ b/tests/tests.vala
@@ -75,7 +75,7 @@ public int main (string[] args) {
Test.add_func ("/router/invoke/propagate_state", test_router_invoke_propagate_state);
Test.add_func ("/router/then", test_router_then);
- Test.add_func ("/router/then/preserve_matching_stack", test_router_then_preserve_matching_stack);
+ Test.add_func ("/router/then/preserve_matching_context", test_router_then_preserve_matching_context);
Test.add_func ("/router/error", test_router_error);