nitcorn project, provides HttpFactory and ActionHttpServer instances, and hold the libevent base handler
			nitcorn :: reactor $ Interfaces
A list of interfaces with dynamic port listenersnitcorn :: reactor $ VirtualHosts
A list of virtual hosts with dynamic port listenersHttpServer instances, and hold the libevent base handler
			nitcorn :: reactor $ Interfaces
A list of interfaces with dynamic port listenersnitcorn :: reactor $ VirtualHosts
A list of virtual hosts with dynamic port listenersHttpRequest class and services to create it
			Serializable::inspect to show more useful information
			serialization :: serialization_core
Abstract services to serialize Nit objects to different formatscore :: union_find
union–find algorithm using an efficient disjoint-set data structuremore_collections :: more_collections
Highly specific, but useful, collections-related classes.FileServer action, which is a standard and minimal file server
			restful annotation documented at lib/nitcorn/restful.nit
			root to execute
			
# Core of the `nitcorn` project, provides `HttpFactory` and `Action`
module reactor
import more_collections
import vararg_routes
import http_request
import http_request_buffer
import http_response
# A server handling a single connection
class HttpServer
	super HTTPConnection
	# The associated `HttpFactory`
	var factory: HttpFactory
	private var parser = new HttpRequestParser is lazy
	# Human readable address of the remote client
	var remote_address: String
	redef fun read_http_request(str)
	do
		var request_object = parser.parse_http_request(str.to_s)
		if request_object != null then delegate_answer request_object
	end
	# Answer to a request
	fun delegate_answer(request: HttpRequest)
	do
		# Find target virtual host
		var virtual_host = null
		if request.header.keys.has("Host") then
			var host = request.header["Host"]
			if host.index_of(':') == -1 then host += ":80"
			for vh in factory.config.virtual_hosts do
				for i in vh.interfaces do if i.to_s == host then
					virtual_host = vh
					break label
				end
			end label
		end
		# Use default virtual host if none already responded
		if virtual_host == null then virtual_host = factory.config.default_virtual_host
		# Get a response from the virtual host
		var response
		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.resolve_path(request)
				var turi
				if root != null then
					turi = ("/" + request.uri.substring_from(root.length)).simplify_path
				else turi = request.uri
				# Delegate the responsibility to respond to the `Action`
				handler.prepare_respond_and_close(request, turi, self)
				return
			else response = new HttpResponse(404)
		else response = new HttpResponse(404)
		respond response
		close
	end
	# Send back `response` to the client
	fun respond(response: HttpResponse)
	do
		response.render.write_to(self)
		for path in response.files do write_file path
	end
end
redef abstract class Action
	# Prepare a `HttpResponse` destined to the client in response to the `request`
	#
	# `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
class HttpFactory
	super ConnectionFactory
	# Configuration of this server
	#
	# It should be populated after this object has instanciated
	var config = new ServerConfig.with_factory(self)
	# 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)
	redef fun spawn_connection(buf_ev, address) do return new HttpServer(buf_ev, self, address)
	# Execute the main listening loop to accept connections
	#
	# After the loop ends, the underlying resources are freed.
	#
	# When the environment variable `NIT_TESTING` is set to `true`,
	# the loop is not executed but the resources are still freed.
	fun run
	do
		if "NIT_TESTING".environ != "true" then
			event_base.dispatch
		end
		event_base.free
	end
end
redef class ServerConfig
	# Handle to retreive the `HttpFactory` on config change
	private var factory: HttpFactory is noinit
	private init with_factory(factory: HttpFactory) do self.factory = factory
end
redef class Sys
	# Active listeners
	private var listeners = new HashMap2[String, Int, ConnectionListener]
	# Hosts needong each listener
	private var listeners_count = new HashMap2[String, Int, Int]
	# Activate a listener on `interfac` if there's not already one
	private fun listen_on(interfac: Interface, factory: HttpFactory)
	do
		if interfac.registered then return
		var name = interfac.name
		var port = interfac.port
		var listener = listeners[name, port]
		if listener == null then
			listener = factory.bind_tcp(name, port)
			if listener != null then
				sys.listeners[name, port] = listener
				listeners_count[name, port] = 1
			end
		else
			var value = listeners_count[name, port].as(not null)
			listeners_count[name, port] = value + 1
		end
		interfac.registered = true
	end
	# TODO close listener
end
redef class Interface
	# Has `self` been registered by `listen_on`?
	private var registered = false
end
redef class Interfaces
	redef fun add(e)
	do
		super
		var config = virtual_host.server_config
		if config != null then register_and_listen(e, config)
	end
	# Indirection to `listen_on` and check if this targets all addresses
	private fun register_and_listen(e: Interface, config: ServerConfig)
	do
		listen_on(e, config.factory)
		if e.name == "0.0.0.0" or e.name == "::0" then config.default_virtual_host = virtual_host
	end
	# TODO remove
end
redef class VirtualHosts
	redef fun add(e)
	do
		super
		for i in e.interfaces do e.interfaces.register_and_listen(i, config)
	end
	# TODO remove
end
lib/nitcorn/reactor.nit:19,1--226,3