class
HTTP::Server
Overview
A concurrent HTTP server implementation.
A server is initialized with a handler chain responsible for processing each incoming request.
NOTE To useServer, you must explicitly import it withrequire "http/server"
require "http/server"
server = HTTP::Server.new do |context|
context.response.content_type = "text/plain"
context.response.print "Hello world!"
end
address = server.bind_tcp 8080
puts "Listening on http://#{address}"
server.listen
Request processing
The handler chain receives an instance ofHTTP::Server::Context that holds
theHTTP::Request to process and aHTTP::Server::Response which it can
configure and write to.
Each connection is processed concurrently in a separateFiber and can handle
multiple subsequent requests-response cycles with connection keep-alive.
Handler chain
The handler given to a server can simply be a block that receives anHTTP::Server::Context,
or it can be an instance ofHTTP::Handler. AnHTTP::Handler has a#next
method to forward processing to the next handler in the chain.
For example, an initial handler might handle exceptions raised from subsequent
handlers and return a500 Server Error status (seeHTTP::ErrorHandler).
The next handler might log all incoming requests (seeHTTP::LogHandler).
And the final handler deals with routing and application logic.
require "http/server"
server = HTTP::Server.new([
HTTP::ErrorHandler.new,
HTTP::LogHandler.new,
HTTP::CompressHandler.new,
HTTP::StaticFileHandler.new("."),
])
server.bind_tcp "127.0.0.1", 8080
server.listen
Response object
TheHTTP::Server::Response object hasstatus andheaders properties that can be
configured before writing the response body. Once any response output has been
written, changing thestatus andheaders properties has no effect.
TheHTTP::Server::Response is a write-onlyIO, so allIO methods are available
on it for sending the response body.
Binding to sockets
The server can be bound to one or more server sockets (see#bind)
Supported types:
- TCP socket:
#bind_tcp,#bind_unused_port - TCP socket with TLS/SSL:
#bind_tls - Unix socket
#bind_unix
#bind(uri : URI) and#bind(uri : String) parse socket configuration for
one of these types from anURI. This can be useful for injecting plain text
configuration values.
Each of these methods returns theSocket::Address that was added to this
server.
require "http/server"
server = HTTP::Server.new do |context|
context.response.content_type = "text/plain"
context.response.print "Hello world!"
end
address = server.bind_tcp "0.0.0.0", 8080
puts "Listening on http://#{address}"
server.listen
It is also possible to bind a genericSocket::Server using
#bind(socket : Socket::Server) which can be used for custom network protocol
configurations.
Server loop
After defining all server sockets to listen to, the server can be started by
calling#listen. This call blocks until the server is closed.
A server can be closed by calling#close. This closes the server sockets and
stops processing any new requests, even on connections with keep-alive enabled.
Currently processing requests are not interrupted but also not waited for.
In order to give them some grace period for finishing, the calling context
can add a timeout likesleep 10.seconds after#listen returns.
Reusing connections
The request processor supports reusing a connection for subsequent
requests. This is used by default for HTTP/1.1 or when requested by
theConnection: keep-alive header. This is signalled by this header being
set on theHTTP::Server::Response when it's passed into the handler chain.
If in the handler chain this header is overridden toConnection: close, then
the connection will not be reused after the request has been processed.
Reusing the connection also requires that the request body (if present) is entirely consumed in the handler chain. Otherwise the connection will be closed.
Defined in:
http/server.crhttp/server/context.cr
http/server/response.cr
Constant Summary
-
Log =
::Log.for("http.server")
Constructors
-
.new(handlers : Indexable(HTTP::Handler), &handler : HTTP::Handler::HandlerProc) : self
Creates a new HTTP server with a handler chain constructed from thehandlers array and the given block.
-
.new(&handler : HTTP::Handler::HandlerProc) : self
Creates a new HTTP server with the given block as handler.
-
.new(handlers : Indexable(HTTP::Handler)) : self
Creates a new HTTP server with thehandlers array as handler chain.
-
.new(handler : HTTP::Handler | HTTP::Handler::HandlerProc)
Creates a new HTTP server with the givenhandler.
Class Method Summary
-
.build_middleware(handlers : Indexable(HTTP::Handler), last_handler : Context -> | Nil = nil) : HTTP::Handler
Builds all handlers as the middleware for
HTTP::Server.
Instance Method Summary
- #addresses : Array(Socket::Address)
-
#bind(uri : String) : Socket::Address
Parses a socket configuration fromuri and adds it to this server.
-
#bind(uri : URI) : Socket::Address
Parses a socket configuration fromuri and adds it to this server.
-
#bind(socket : Socket::Server) : Nil
Adds a
Socket::Serversocket to this server. -
#bind_tcp(host : String, port : Int32, reuse_port : Bool = false) : Socket::IPAddress
Creates a
TCPServerlistening onhost:portand adds it as a socket, returning the local address and port the server listens on. -
#bind_tcp(port : Int32, reuse_port : Bool = false) : Socket::IPAddress
Creates a
TCPServerlistening on127.0.0.1:portand adds it as a socket, returning the local address and port the server listens on. -
#bind_tcp(address : Socket::IPAddress, reuse_port : Bool = false) : Socket::IPAddress
Creates a
TCPServerlistening onaddress and adds it as a socket, returning the local address and port the server listens on. -
#bind_tls(host : String, port : Int32, context : OpenSSL::SSL::Context::Server, reuse_port : Bool = false) : Socket::IPAddress
Creates an
OpenSSL::SSL::Serverand adds it as a socket. -
#bind_tls(host : String, context : OpenSSL::SSL::Context::Server) : Socket::IPAddress
Creates an
OpenSSL::SSL::Serverand adds it as a socket. -
#bind_tls(address : Socket::IPAddress, context : OpenSSL::SSL::Context::Server) : Socket::IPAddress
Creates an
OpenSSL::SSL::Serverand adds it as a socket. -
#bind_unix(path : String) : Socket::UNIXAddress
Creates a
UNIXServerbound topath and adds it as a socket. -
#bind_unix(address : Socket::UNIXAddress) : Socket::UNIXAddress
Creates a
UNIXServerbound toaddress and adds it as a socket. -
#bind_unused_port(host : String = Socket::IPAddress::LOOPBACK, reuse_port : Bool = false) : Socket::IPAddress
Creates a
TCPServerlistening on an unused port and adds it as a socket. -
#close : Nil
Gracefully terminates the server.
-
#closed? : Bool
Returns
trueif this server is closed. -
#each_address(&block : Socket::Address -> )
Enumerates all addresses this server is bound to.
-
#listen(port : Int32, reuse_port : Bool = false)
Creates a
TCPServerlistening on127.0.0.1:port, adds it as a socket and starts the server. -
#listen(host : String, port : Int32, reuse_port : Bool = false)
Creates a
TCPServerlistening onhost:port, adds it as a socket and starts the server. -
#listen : Nil
Starts the server.
-
#listening? : Bool
Returns
trueif this server is listening on its sockets. -
#max_headers_size : Int32
Returns the maximum permitted combined size for the headers in an HTTP request.
-
#max_headers_size=(size : Int32) : Int32
Sets the maximum permitted combined size for the headers in an HTTP request.
-
#max_request_line_size : Int32
Returns the maximum permitted size for the request line in an HTTP request.
-
#max_request_line_size=(size : Int32) : Int32
Sets the maximum permitted size for the request line in an HTTP request.
Instance methods inherited from class Reference
==(other : self)==(other : JSON::Any)
==(other : YAML::Any)
==(other) ==, dup dup, hash(hasher) hash, initialize initialize, inspect(io : IO) : Nil inspect, object_id : UInt64 object_id, pretty_print(pp) : Nil pretty_print, same?(other : Reference) : Bool
same?(other : Nil) same?, to_s(io : IO) : Nil to_s
Constructor methods inherited from class Reference
new
new,
unsafe_construct(address : Pointer, *args, **opts) : self
unsafe_construct
Class methods inherited from class Reference
pre_initialize(address : Pointer)
pre_initialize
Instance methods inherited from class Object
! : Bool
!,
!=(other)
!=,
!~(other)
!~,
==(other)
==,
===(other : JSON::Any)===(other : YAML::Any)
===(other) ===, =~(other) =~, as(type : Class) as, as?(type : Class) as?, class class, dup dup, hash(hasher)
hash hash, in?(collection : Object) : Bool
in?(*values : Object) : Bool in?, inspect(io : IO) : Nil
inspect : String inspect, is_a?(type : Class) : Bool is_a?, itself itself, nil? : Bool nil?, not_nil!(message)
not_nil! not_nil!, pretty_inspect(width = 79, newline = "\n", indent = 0) : String pretty_inspect, pretty_print(pp : PrettyPrint) : Nil pretty_print, responds_to?(name : Symbol) : Bool responds_to?, tap(&) tap, to_json(io : IO) : Nil
to_json : String to_json, to_pretty_json(indent : String = " ") : String
to_pretty_json(io : IO, indent : String = " ") : Nil to_pretty_json, to_s(io : IO) : Nil
to_s : String to_s, to_yaml(io : IO) : Nil
to_yaml : String to_yaml, try(&) try, unsafe_as(type : T.class) forall T unsafe_as
Class methods inherited from class Object
from_json(string_or_io : String | IO, root : String)from_json(string_or_io : String | IO) from_json, from_yaml(string_or_io : String | IO) from_yaml
Macros inherited from class Object
class_getter(*names, &block)
class_getter,
class_getter!(*names)
class_getter!,
class_getter?(*names, &block)
class_getter?,
class_property(*names, &block)
class_property,
class_property!(*names)
class_property!,
class_property?(*names, &block)
class_property?,
class_setter(*names)
class_setter,
def_clone
def_clone,
def_equals(*fields)
def_equals,
def_equals_and_hash(*fields)
def_equals_and_hash,
def_hash(*fields)
def_hash,
delegate(*methods, to object)
delegate,
forward_missing_to(delegate)
forward_missing_to,
getter(*names, &block)
getter,
getter!(*names)
getter!,
getter?(*names, &block)
getter?,
property(*names, &block)
property,
property!(*names)
property!,
property?(*names, &block)
property?,
setter(*names)
setter
Constructor Detail
Creates a new HTTP server with a handler chain constructed from thehandlers array and the given block.
Creates a new HTTP server with the given block as handler.
Creates a new HTTP server with thehandlers array as handler chain.
Creates a new HTTP server with the givenhandler.
Class Method Detail
Builds all handlers as the middleware forHTTP::Server.
Instance Method Detail
Parses a socket configuration fromuri and adds it to this server. Returns the effective address it is bound to.
require "http/server"
server = HTTP::Server.new { }
server.bind("tcp://localhost:80") # => Socket::IPAddress.new("127.0.0.1", 8080)
server.bind("unix:///tmp/server.sock") # => Socket::UNIXAddress.new("/tmp/server.sock")
server.bind("tls://127.0.0.1:443?key=private.key&cert=certificate.cert&ca=ca.crt") # => Socket::IPAddress.new("127.0.0.1", 443)
Parses a socket configuration fromuri and adds it to this server. Returns the effective address it is bound to.
require "http/server"
server = HTTP::Server.new { }
server.bind("tcp://localhost:80") # => Socket::IPAddress.new("127.0.0.1", 8080)
server.bind("unix:///tmp/server.sock") # => Socket::UNIXAddress.new("/tmp/server.sock")
server.bind("tls://127.0.0.1:443?key=private.key&cert=certificate.cert&ca=ca.crt") # => Socket::IPAddress.new("127.0.0.1", 443)
Creates aTCPServer listening onhost:port and adds it as a socket, returning the local address
and port the server listens on.
require "http/server"
server = HTTP::Server.new { }
server.bind_tcp("127.0.0.100", 8080) # => Socket::IPAddress.new("127.0.0.100", 8080)
Ifreuse_port istrue, it enables theSO_REUSEPORT socket option,
which allows multiple processes to bind to the same port.
Creates aTCPServer listening on127.0.0.1:port and adds it as a socket,
returning the local address and port the server listens on.
require "http/server"
server = HTTP::Server.new { }
server.bind_tcp(8080) # => Socket::IPAddress.new("127.0.0.1", 8080)
Ifreuse_port istrue, it enables theSO_REUSEPORT socket option,
which allows multiple processes to bind to the same port.
Creates aTCPServer listening onaddress and adds it as a socket, returning the local address
and port the server listens on.
require "http/server"
server = HTTP::Server.new { }
server.bind_tcp(Socket::IPAddress.new("127.0.0.100", 8080)) # => Socket::IPAddress.new("127.0.0.100", 8080)
server.bind_tcp(Socket::IPAddress.new("127.0.0.100", 0)) # => Socket::IPAddress.new("127.0.0.100", 35487)
Ifreuse_port istrue, it enables theSO_REUSEPORT socket option,
which allows multiple processes to bind to the same port.
Creates anOpenSSL::SSL::Server and adds it as a socket.
The SSL server wraps aTCPServer listening onhost:port.
require "http/server"
server = HTTP::Server.new { }
context = OpenSSL::SSL::Context::Server.new
context.certificate_chain = "openssl.crt"
context.private_key = "openssl.key"
server.bind_tls "127.0.0.1", 8080, context
Creates anOpenSSL::SSL::Server and adds it as a socket.
The SSL server wraps aTCPServer listening on an unused port onhost.
require "http/server"
server = HTTP::Server.new { }
context = OpenSSL::SSL::Context::Server.new
context.certificate_chain = "openssl.crt"
context.private_key = "openssl.key"
address = server.bind_tls "127.0.0.1", context
Creates anOpenSSL::SSL::Server and adds it as a socket.
The SSL server wraps aTCPServer listening on an unused port onhost.
require "http/server"
server = HTTP::Server.new { }
context = OpenSSL::SSL::Context::Server.new
context.certificate_chain = "openssl.crt"
context.private_key = "openssl.key"
address = server.bind_tls Socket::IPAddress.new("127.0.0.1", 8000), context
Creates aUNIXServer bound topath and adds it as a socket.
require "http/server"
server = HTTP::Server.new { }
server.bind_unix "/tmp/my-socket.sock"
Creates aUNIXServer bound toaddress and adds it as a socket.
require "http/server"
server = HTTP::Server.new { }
server.bind_unix(Socket::UNIXAddress.new("/tmp/my-socket.sock"))
Creates aTCPServer listening on an unused port and adds it as a socket.
Returns theSocket::IPAddress with the determined port number.
require "http/server"
server = HTTP::Server.new { }
server.bind_unused_port # => Socket::IPAddress.new("127.0.0.1", 12345)
Gracefully terminates the server. It will process currently accepted requests, but it won't accept new connections.
Creates aTCPServer listening on127.0.0.1:port, adds it as a socket
and starts the server. Blocks until the server is closed.
See#bind(port : Int32) for details.
Creates aTCPServer listening onhost:port, adds it as a socket
and starts the server. Blocks until the server is closed.
See#bind(host : String, port : Int32) for details.
Returns the maximum permitted combined size for the headers in an HTTP request.
When parsing a request, the server keeps track of the amount of total bytes
consumed for all headers (including line breaks).
If combined byte size of all headers is larger than the permitted size,
the server responds with the status code432 Request Header Fields Too Large
(seeHTTP::Status::REQUEST_HEADER_FIELDS_TOO_LARGE).
Default:HTTP::MAX_HEADERS_SIZE
Sets the maximum permitted combined size for the headers in an HTTP request.
Returns the maximum permitted size for the request line in an HTTP request.
The request line is the first line of a request, consisting of method,
resource and HTTP version and the delimiting line break.
If the request line has a larger byte size than the permitted size,
the server responds with the status code414 URI Too Long (seeHTTP::Status::URI_TOO_LONG).
Default:HTTP::MAX_REQUEST_LINE_SIZE