X-Git-Url: http://nitlanguage.org?ds=sidebyside diff --git a/lib/nitcorn/reactor.nit b/lib/nitcorn/reactor.nit index 1a56ee8..5bd285d 100644 --- a/lib/nitcorn/reactor.nit +++ b/lib/nitcorn/reactor.nit @@ -2,6 +2,7 @@ # # Copyright 2013 Jean-Philippe Caissy # Copyright 2014 Alexis Laferrière +# Copyright 2014 Alexandre Terrasa # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -19,32 +20,24 @@ module reactor import more_collections -import libevent -import server_config +import vararg_routes import http_request +import http_request_buffer import http_response # A server handling a single connection class HttpServer - super Connection + super HTTPConnection # The associated `HttpFactory` var factory: HttpFactory - # Init the server using `HttpFactory`. - init(buf_ev: NativeBufferEvent, factory: HttpFactory) is old_style_init do - self.factory = factory - end - private var parser = new HttpRequestParser is lazy - redef fun read_callback(str) + redef fun read_http_request(str) do - # TODO support bigger inputs (such as big forms and file upload) - var request_object = parser.parse_http_request(str.to_s) - if request_object != null then delegate_answer request_object end @@ -72,31 +65,56 @@ class HttpServer if virtual_host != null then var route = virtual_host.routes[request.uri] if route != null then + # include uri parameters in request + request.uri_params = route.parse_params(request.uri) + var handler = route.handler var root = route.path var turi if root != null then turi = ("/" + request.uri.substring_from(root.length)).simplify_path else turi = request.uri - response = handler.answer(request, turi) + + # Delegate the responsibility to respond to the `Action` + handler.prepare_respond_and_close(request, turi, self) + return else response = new HttpResponse(405) else response = new HttpResponse(405) - # Send back a response - write response.to_s + respond response close end + + # Send back `response` to the client + fun respond(response: HttpResponse) + do + write response.to_s + for path in response.files do write_file path + end end redef abstract class Action - # Handle a request with the relative URI `truncated_uri` + # Prepare a `HttpResponse` destined to the client in response to the `request` # - # `request` is fully formed request object and has a reference to the session - # if one preexists. + # `request` is fully formed request object with a reference to the session + # if one already exists. # # `truncated_uri` is the ending of the full request URI, truncated from the route # leading to this `Action`. fun answer(request: HttpRequest, truncated_uri: String): HttpResponse is abstract + + # Full to a `request` with sending the response and closing of the `http_server` + # + # Must users only need to implement `answer`, this method is for advanced use only. + # It can be used to delay an answer until an event is raised or work is done on a different thread. + # + # By default this method calls `answer`, relays the response to `http_server.respond` and closes `http_server`. + protected fun prepare_respond_and_close(request: HttpRequest, truncated_uri: String, http_server: HttpServer) + do + var response = answer(request, truncated_uri) + http_server.respond response + http_server.close + end end # Factory to create `HttpServer` instances, and hold the libevent base handler @@ -108,7 +126,7 @@ class HttpFactory # It should be populated after this object has instanciated var config = new ServerConfig.with_factory(self) - # Instanciate a server and libvent + # Instantiate a server and libvent # # You can use this to create the first `HttpFactory`, which is the most common. init and_libevent do init(new NativeEventBase)