Core of the nitcorn project, provides HttpFactory and Action

Introduced classes

class HttpFactory

nitcorn :: HttpFactory

Factory to create HttpServer instances, and hold the libevent base handler
class HttpServer

nitcorn :: HttpServer

A server handling a single connection

Redefined classes

redef abstract class Action

nitcorn :: reactor $ Action

Action executed to answer a request
redef class Interface

nitcorn :: reactor $ Interface

An interface composed of a name:port
redef class Interfaces

nitcorn :: reactor $ Interfaces

A list of interfaces with dynamic port listeners
redef class ServerConfig

nitcorn :: reactor $ ServerConfig

Server instance configuration
redef class Sys

nitcorn :: reactor $ Sys

The main class of the program.
redef class VirtualHosts

nitcorn :: reactor $ VirtualHosts

A list of virtual hosts with dynamic port listeners

All class definitions

redef abstract class Action

nitcorn :: reactor $ Action

Action executed to answer a request
class HttpFactory

nitcorn $ HttpFactory

Factory to create HttpServer instances, and hold the libevent base handler
class HttpServer

nitcorn $ HttpServer

A server handling a single connection
redef class Interface

nitcorn :: reactor $ Interface

An interface composed of a name:port
redef class Interfaces

nitcorn :: reactor $ Interfaces

A list of interfaces with dynamic port listeners
redef class ServerConfig

nitcorn :: reactor $ ServerConfig

Server instance configuration
redef class Sys

nitcorn :: reactor $ Sys

The main class of the program.
redef class VirtualHosts

nitcorn :: reactor $ VirtualHosts

A list of virtual hosts with dynamic port listeners
package_diagram nitcorn::reactor reactor more_collections more_collections nitcorn::reactor->more_collections nitcorn::vararg_routes vararg_routes nitcorn::reactor->nitcorn::vararg_routes nitcorn::http_request_buffer http_request_buffer nitcorn::reactor->nitcorn::http_request_buffer nitcorn::http_response http_response nitcorn::reactor->nitcorn::http_response serialization serialization more_collections->serialization poset poset more_collections->poset nitcorn::server_config server_config nitcorn::vararg_routes->nitcorn::server_config nitcorn::http_request http_request nitcorn::vararg_routes->nitcorn::http_request libevent libevent nitcorn::http_request_buffer->libevent nitcorn::http_response->serialization template template nitcorn::http_response->template ...serialization ... ...serialization->serialization ...poset ... ...poset->poset ...nitcorn::server_config ... ...nitcorn::server_config->nitcorn::server_config ...nitcorn::http_request ... ...nitcorn::http_request->nitcorn::http_request ...libevent ... ...libevent->libevent ...template ... ...template->template nitcorn::file_server file_server nitcorn::file_server->nitcorn::reactor nitcorn::signal_handler signal_handler nitcorn::signal_handler->nitcorn::reactor nitcorn::log log nitcorn::log->nitcorn::reactor nitcorn::proxy proxy nitcorn::proxy->nitcorn::reactor nitcorn::nitcorn nitcorn nitcorn::nitcorn->nitcorn::file_server nitcorn::nitcorn->nitcorn::signal_handler nitcorn::nitcorn... ... nitcorn::nitcorn...->nitcorn::nitcorn a_star-m a_star-m a_star-m->nitcorn::log a_star-m... ... a_star-m...->a_star-m nitcorn::nitcorn_reverse_proxy nitcorn_reverse_proxy nitcorn::nitcorn_reverse_proxy->nitcorn::proxy nitcorn::nitcorn_reverse_proxy... ... nitcorn::nitcorn_reverse_proxy...->nitcorn::nitcorn_reverse_proxy

Ancestors

module abstract_collection

core :: abstract_collection

Abstract collection classes and services.
module abstract_text

core :: abstract_text

Abstract class for manipulation of sequences of characters
module array

core :: array

This module introduces the standard array structure.
module bitset

core :: bitset

Services to handle BitSet
module bytes

core :: bytes

Services for byte streams and arrays
module caching

serialization :: caching

Services for caching serialization engines
module circular_array

core :: circular_array

Efficient data structure to access both end of the sequence.
module codec_base

core :: codec_base

Base for codecs to use with streams
module codecs

core :: codecs

Group module for all codec-related manipulations
module collection

core :: collection

This module define several collection classes.
module core

core :: core

Standard classes and methods used by default by Nit programs and libraries.
module engine_tools

serialization :: engine_tools

Advanced services for serialization engines
module environ

core :: environ

Access to the environment variables of the process
module error

core :: error

Standard error-management infrastructure.
module exec

core :: exec

Invocation and management of operating system sub-processes.
module file

core :: file

File manipulations (create, read, write, etc.)
module fixed_ints

core :: fixed_ints

Basic integers of fixed-precision
module fixed_ints_text

core :: fixed_ints_text

Text services to complement fixed_ints
module flat

core :: flat

All the array-based text representations
module gc

core :: gc

Access to the Nit internal garbage collection mechanism
module hash_collection

core :: hash_collection

Introduce HashMap and HashSet.
module http_request

nitcorn :: http_request

Provides the HttpRequest class and services to create it
module inspect

serialization :: inspect

Refine Serializable::inspect to show more useful information
module iso8859_1

core :: iso8859_1

Codec for ISO8859-1 I/O
module kernel

core :: kernel

Most basic classes and methods.
module libevent

libevent :: libevent

Low-level wrapper around the libevent library to manage events on file descriptors
module list

core :: list

This module handle double linked lists
module math

core :: math

Mathematical operations
module meta

meta :: meta

Simple user-defined meta-level to manipulate types of instances as object.
module native

core :: native

Native structures for text and bytes
module numeric

core :: numeric

Advanced services for Numeric types
module poset

poset :: poset

Pre order sets and partial order set (ie hierarchies)
module protocol

core :: protocol

module queue

core :: queue

Queuing data structures and wrappers
module range

core :: range

Module for range of discrete objects.
module re

core :: re

Regular expression support for all services based on Pattern
module ropes

core :: ropes

Tree-based representation of a String.
module serialization

serialization :: serialization

General serialization services
module serialization_core

serialization :: serialization_core

Abstract services to serialize Nit objects to different formats
module server_config

nitcorn :: server_config

Classes and services to configure the server
module sorter

core :: sorter

This module contains classes used to compare things and sorts arrays.
module stream

core :: stream

Input and output streams of characters
module template

template :: template

Basic template system
module text

core :: text

All the classes and methods related to the manipulation of text entities
module time

core :: time

Management of time and dates
module union_find

core :: union_find

union–find algorithm using an efficient disjoint-set data structure
module utf8

core :: utf8

Codec for UTF-8 I/O

Parents

module http_request_buffer

nitcorn :: http_request_buffer

Http request parsing for buffered inputs.
module http_response

nitcorn :: http_response

Provides the HttpResponse class and http_status_codes
module more_collections

more_collections :: more_collections

Highly specific, but useful, collections-related classes.
module vararg_routes

nitcorn :: vararg_routes

Routes with parameters.

Children

module file_server

nitcorn :: file_server

Provides the FileServer action, which is a standard and minimal file server
module log

nitcorn :: log

Services inserting a timestamp in all prints and to log each requests
module proxy

nitcorn :: proxy

Provides the ProxyAction action, which redirects requests to another interface
module signal_handler

nitcorn :: signal_handler

Handle SIGINT and SIGTERM to close the server after all active events

Descendants

module a_star-m

a_star-m

module example_angular

popcorn :: example_angular

This is an example of how to use angular.js with popcorn
module hooks

github :: hooks

Github hook event listening with nitcorn.
module htcpcp_server

nitcorn :: htcpcp_server

A server that implements HTCPCP. At the moment there are no additions.
module loader

github :: loader

module nitcorn

nitcorn :: nitcorn

The nitcorn Web server framework creates server-side Web apps in Nit
module nitcorn_hello_world

nitcorn :: nitcorn_hello_world

Hello World Web server example
module nitcorn_reverse_proxy

nitcorn :: nitcorn_reverse_proxy

Minimal example using a ProxyAction
module pop_auth

popcorn :: pop_auth

Authentification handlers.
module pop_handlers

popcorn :: pop_handlers

Route handlers.
module pop_json

popcorn :: pop_json

Introduce useful services for JSON REST API handlers.
module pop_routes

popcorn :: pop_routes

Internal routes representation.
module pop_sessions

popcorn :: pop_sessions

Session handlers
module pop_tasks

popcorn :: pop_tasks

Popcorn threaded tasks
module pop_templates

popcorn :: pop_templates

Template rendering for popcorn
module pop_tests

popcorn :: pop_tests

Popcorn testing services
module popcorn

popcorn :: popcorn

Application server abstraction on top of nitcorn.
module pthreads

nitcorn :: pthreads

Activate the use of pthreads with nitcorn
module restful

nitcorn :: restful

Support module for the nitrestful tool and the restful annotation
module restful_annot

nitcorn :: restful_annot

Example for the restful annotation documented at lib/nitcorn/restful.nit
module simple_file_server

nitcorn :: simple_file_server

Basic file server on port 80 by default, may require 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