Skip to content

Commit

Permalink
WIP: update documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
arteymix committed May 27, 2015
1 parent 5ec8e3d commit 65d8ca4
Show file tree
Hide file tree
Showing 11 changed files with 145 additions and 38 deletions.
2 changes: 1 addition & 1 deletion docs/application.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ utilities.
.. code:: vala
app.get ("", (req, res) => {
res.write ("Hello world!".data);
res.body.write ("Hello world!".data);
});
Every route declaration has a callback associated that does the request
Expand Down
30 changes: 29 additions & 1 deletion docs/ctpl.rst
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,33 @@ application can produce very big output efficiently.
app.get ("", (req, res) => {
var template = new View.from_string ("");
template.stream (res);
template.stream (res.body);
res.end ();
});
It is unfortunately not possible to stream with non-blocking I/O due to the
design of CTPL. The only possibility would be to dump the template in
a temporary ``MemoryOutputStream`` and then splice it asynchronously in the
response body.

.. code:: vala
app.get ("", (req, res) => {
var template = new View.from_string ("");
var buffer = new MemoryOutputStream.resizable ();
// blocking on memory I/O
template.stream (buffer);
var buffer_reader = new MemoryInputStream (buffer.data);
// non-blocking on network I/O
res.body.splice_async.begin (buffer_reader,
OutputStreamSpliceFlags.CLOSE_SOURCE,
Priority.DEFAULT,
null,
(obj, result) => {
var spliced = res.body.splice_async.end (result);
res.end ();
});
});
3 changes: 2 additions & 1 deletion docs/getting-started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ changes in the framework.
var app = new Router ();
app.get("", (req, res) => {
res.write ("Hello world!".data);
res.body.write ("Hello world!".data);
res.end ();
});
new Server (app).run ({"app", "--port", "3003"});
Expand Down
6 changes: 5 additions & 1 deletion docs/persistency.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ maintained in nemequ/vala-extra-vapis GitHub repository.
Memcached.ReturnCode error;
var value = memcached.get ("hello", out flags, out error);
res.write (value);
res.body.write (value);
res.end ();
});
app.post ("<key>", (req, res) => {
Expand All @@ -57,4 +59,6 @@ maintained in nemequ/vala-extra-vapis GitHub repository.
var value = memcached.get ("hello", out flags, out error);
res.write (value);
res.end ();
});
8 changes: 6 additions & 2 deletions docs/redirection-and-error.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ setting the status and returning from the function.
The :doc:`router` handler will automatically catch these special errors and set
the appropriate status code in the response for your convenience.

Also, the :doc:`vsgi/response` will be automatically ended, so you do not have
to trickily end it yourself.

Redirection (3xx)
-----------------

Expand All @@ -26,15 +29,16 @@ use the message as a redirect URL.
if (user.save ())
throw new Redirection.MOVED_TEMPORAIRLY ("/user/%u".printf (user.id));
res.end ();
});
Client (4xx) and server (5xx) error
-----------------------------------

Just like for redirection, client and server errors are thrown.

Errors are predefined in ``ClientError`` and ``ServerError``
enumerations.
Errors are predefined in ``ClientError`` and ``ServerError`` enumerations.

.. code:: vala
Expand Down
17 changes: 11 additions & 6 deletions docs/route.rst
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,9 @@ and optimized.
.. code:: vala
app.regex (Request.GET, /home\/?/, (req, res) => {
var writer = new DataOutputStream (res);
var writer = new DataOutputStream (res.body);
writer.put_string ("Matched using a regular expression.");
res.end ();
});
Matching using a callback
Expand All @@ -147,8 +148,9 @@ A matcher consist of a callback matching a given ``Request`` object.
Route.Matcher matcher = (req) => { req.path == "/custom-matcher"; };
app.matcher ("GET", matcher, (req, res) => {
var writer = new DataOutputStream (res);
var writer = new DataOutputStream (res.body);
writer.put_string ("Matched using a custom matcher.");
res.end ();
});
You could, for instance, match the request if the user is an administrator and
Expand All @@ -159,10 +161,13 @@ fallback to a default route otherwise.
app.matcher ("GET", (req) => {
var user = new User (req.query["id"]);
return "admin" in user.roles;
}, (req, res) => {});
}, (req, res) => {
// ...
});
app.route ("<any:path>", (req, res) => {
res.status = 404;
res.end ();
});
Combining custom matcher with existing matcher
Expand Down Expand Up @@ -220,11 +225,11 @@ work.
app.get ("", (req, res) => {
// write now and block
res.write ("Hello world!".data);
res.body.write ("Hello world!".data);
res.write_async.begin ("Hello world!".data, (obj, r) => {
res.body.write_async.begin ("Hello world!".data, (obj, r) => {
var written = res.write_async.end (r);
res.close ();
res.end ();
});
// keep processing while the response is begin written
Expand Down
6 changes: 4 additions & 2 deletions docs/router.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ the ``application/x-www-form-urlencoded`` body of the :doc:`vsgi/request`.
.. code:: vala
app.post ("login", (req, res) => {
var buffer = new MemoryOutputStream (null, realloc, free);
var buffer = new MemoryOutputStream.resizable ();
// consume the request body
buffer.splice (req, OutputStreamSpliceFlags.CLOSE_SOURCE);
buffer.splice (req.body, OutputStreamSpliceFlags.CLOSE_SOURCE);
var data = Soup.Form.decode ((string) buffer.get_data ());
Expand All @@ -44,6 +44,8 @@ the ``application/x-www-form-urlencoded`` body of the :doc:`vsgi/request`.
// assuming you have a session implementation in your app
var session = new Session.authenticated_by (username, password);
res.end ();
});
It is also possible to use a custom HTTP method via the ``method``
Expand Down
6 changes: 3 additions & 3 deletions docs/scripting.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Lua
// GET /lua
app.get ("lua", (req, res) => {
var writer = new DataOutputStream (res);
var writer = new DataOutputStream (res.body);
// evaluate a string containing Lua code
writer.put_string (lua.do_string (
Expand Down Expand Up @@ -68,8 +68,8 @@ Scheme can be used to produce template or facilitate computation.
.. code:: vala
app.get ("hello.scm", (req, res) => {
var writer = new DataOutputStream (res);
res.put_string (scm.run ("scripts/hello.scm"));
var writer = new DataOutputStream (res.body);
writer.put_string (scm.run ("scripts/hello.scm"));
});
Scheme code:
Expand Down
62 changes: 54 additions & 8 deletions docs/vsgi/request.rst
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ property or directly from the request headers.
app.get ("", (req, res) => {
for (var cookie : req.cookies) {
res.write (cookie.get_name ().data);
res.body.write (cookie.get_name ().data);
}
// from the headers
Expand All @@ -103,19 +103,65 @@ Request body is streamed directly from the instance as it inherit from

.. _GLib.InputStream: http://valadoc.org/#!api=gio-2.0/GLib.InputStream

`Soup.Form`_ can be used to parse ``application/x-www-form-urlencoded`` format.

.. _Soup.Form: http://valadoc.org/#!api=libsoup-2.4/Soup.Form

.. code:: vala
app.get ("", (req, res) => {
var buffer = new uint8[24];
req.read (buffer);
app.post ("", (req, res) => {
var buffer = new MemoryOutputStream.resizable ();
// consume the request body in the stream
buffer.splice (req.body, OutputStreamSpliceFlags.CLOSE_SOURCE);
// consume it asynchronously
buffer.splice_async.begin (req.body,
OutputStreamSpliceFlags.CLOSE_SOURCE,
Priority.DEFAULT,
null,
(obj, result) => {
var consumed = buffer.splice_async.end (result);
// decode the data
var data = Soup.Form.decode (buffer.data);
})
});
Implementation will typically consume the status line, headers and newline that
separates the headers from the body. The body is left to your application to
interpret as it can contain pretty much anything.
separates the headers from the body in the base stream at construct time. It
also guarantee that the body has been decoded if any transfer encoding were
applied for the transport.

If the content is encoded with the ``Content-Encoding`` header, it is the
responsibility of your application to decode it properly. VSGI provides common
:doc:`converters` to simplify the task.

The ``body`` property can be setted to perform filtering or redirection. This
example show charset conversion using `GLib.CharsetConverter`_.

.. _GLib.CharsetConverter: http://valadoc.org/#!api=gio-2.0/GLib.CharsetConverter.CharsetConverter

.. code:: vala
app.get ("", (req, res) => {
req.body = new ConverterInputStream (req.body, new CharsetConverter ("utf-8", "ascii"));
var reader = new DataInputStream (req.body);
// pipe the request body in the response body
res.splice (req, OutputStreamSpliceFlags.CLOSE_SOURCE);
res.end ();
});
Multipart body
~~~~~~~~~~~~~~

Multipart body support is planned in a future minor release, more information
on `issue #81`_.

Multipart body are not yet supported, but this is planned for the next minor
release.
.. _issue #81: https://github.com/valum-framework/valum/issues/81

Closing the request
-------------------
Expand Down
41 changes: 29 additions & 12 deletions docs/vsgi/response.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@ Response
Responses are representing resources requested by a client. They are actively
streamed across the network, preferably using non-blocking asynchronous I/O.

Any operations on a response must eventually invoke ``end``, this is how it is
figured out that the response has completed its processing and resources
associated to it can be released. This enables the possibility to keep
a reference to the response in `AsyncResult`.

Status
------

Expand Down Expand Up @@ -54,17 +49,32 @@ headers.
Body
----

The body of a response is streamed directly in the instance since it inherits
from `GLib.OutputStream`_.
The body of a response is accessed through the ``body`` property. It inherits
from `GLib.OutputStream` to provide streaming capabilities.

Status line and headers are sent the first time the property is accessed. It is
considered an error to modify them once the body has been accessed.

The transfer encoding is already handled by the VSGI implementation, so all you
have to do is set the ``Transfer-Encoding`` header properly.

.. _GLib.OutputStream: http://valadoc.org/#!api=gio-2.0/GLib.OutputStream

.. code:: vala
app.get ("", (req, res) => {
res.write ("Hello world!".data);
res.body.write ("Hello world!".data);
});
It is possible to set the ``body`` property in order to filter or redirect it.
This can be used to implement gzipped content encoding or just dump the body in
a file stream for debugging.

.. code:: vala
res.headers.replace ("Content-Encoding", "gzip");
res.body = new ConverterOutputStream (res.body, new ZLibCompressor ());
Closing the response
--------------------

Expand All @@ -85,8 +95,8 @@ a great incidence on the application throughput.
.. code:: vala
app.get("", (req, res) => {
res.write ("You should receive an email shortly...".data);
res.close (); // you can even use close_async
res.body.write ("You should receive an email shortly...".data);
res.body.close (); // you can even use close_async
// send a success mail
Mailer.send ("johndoe@example.com", "Had to close that stream mate!");
Expand All @@ -103,5 +113,12 @@ performances.
});
});
End the response
---------------
Ending the response
-------------------

The ``Response`` defines the ``end`` signal used to notify that the response
has been processed its resources can be freed.

This signal must be emitted during the :doc:`application` handling, otherwise
the response will hang and the client will never see it completed.

2 changes: 1 addition & 1 deletion docs/vsgi/server.rst
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ CLI arguments, so you must write your code in a ``main`` function.
var app = new Router;
app.get ("", (req, res) => {
res.write ("Hello world!".data);
res.body.write ("Hello world!".data);
});
return new Server (app).run (args);
Expand Down

0 comments on commit 65d8ca4

Please sign in to comment.