# class HTTP::Server

- HTTP::Server
- Reference
- Object

## Overview

An HTTP server.

A server is given a handler that receives an `HTTP::Server::Context` that holds the `HTTP::Request` to process and must in turn configure and write to an `HTTP::Server::Response`.

The `HTTP::Server::Response` object has `status` and `headers` properties that can be configured before writing the response body. Once response output is written, changing the `status` and `headers` properties has no effect.

The `HTTP::Server::Response` is also a write-only `IO`, so all `IO` methods are available in it.

The handler given to a server can simply be a block that receives an `HTTP::Server::Context`, or it can be an `HTTP::Handler`. An `HTTP::Handler` has an optional `next` handler, so handlers can be chained. For example, an initial handler may handle exceptions in a subsequent handler and return a 500 status code (see `HTTP::ErrorHandler`), the next handler might log the incoming request (see `HTTP::LogHandler`), and the final handler deals with routing and application logic.

### Simple Setup

A handler is given with a block.

    require "http/server"

    server = HTTP::Server.new do |context|
      context.response.content_type = "text/plain"
      context.response.print "Hello world!"
    end

    server.bind_tcp 8080
    puts "Listening on http://127.0.0.1:8080"
    server.listen

### With non-localhost bind address

    require "http/server"

    server = HTTP::Server.new do |context|
      context.response.content_type = "text/plain"
      context.response.print "Hello world!"
    end

    server.bind_tcp "0.0.0.0", 8080
    puts "Listening on http://0.0.0.0:8080"
    server.listen

### Add handlers

A series of handlers are chained.

    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

### Add handlers and block

A series of handlers is chained, the last one being the given block.

    require "http/server"

    server = HTTP::Server.new([
      HTTP::ErrorHandler.new,
      HTTP::LogHandler.new,
    ]) do |context|
      context.response.content_type = "text/plain"
      context.response.print "Hello world!"
    end

    server.bind_tcp "0.0.0.0", 8080
    server.listen

## Defined in:

## Constructors

- .new(handlers : Array(HTTP::Handler), &handler : HTTP::Handler::HandlerProc) : self

  Creates a new HTTP server with a handler chain constructed from the handlers array and the given block.

- .new(&handler : HTTP::Handler::HandlerProc) : self

  Creates a new HTTP server with the given block as handler.

- .new(handlers : Array(HTTP::Handler)) : self

  Creates a new HTTP server with the handlers array as handler chain.

- .new(handler : HTTP::Handler | HTTP::Handler::HandlerProc)

  Creates a new HTTP server with the given handler.

## Class Method Summary

- .build_middleware(handlers, last_handler : Context -> ? = nil)

  Builds all handlers as the middleware for `HTTP::Server`.

## Instance Method Summary

- #addresses : Array(Socket::Address)
- #bind(socket : Socket::Server) : Nil

  Adds a `Socket::Server` socket to this server.

- #bind(uri : String) : Socket::Address

  Parses a socket configuration from uri and adds it to this server.

- #bind(uri : URI) : Socket::Address

  Parses a socket configuration from uri and adds it to this server.

- #bind_ssl(*args)

  DEPRECATED Use `#bind_tls`.

- #bind_tcp(host : String, port : Int32, reuse_port : Bool = false) : Socket::IPAddress

  Creates a `TCPServer` listenting on `host:port` and 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 `TCPServer` listenting on `127.0.0.1:port` and 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 `TCPServer` listenting on address and adds it as a socket, returning the local address and port the server listens on.

- #bind_tls(address : Socket::IPAddress, context : OpenSSL::SSL::Context::Server) : Socket::IPAddress

  Creates an `OpenSSL::SSL::Server` and adds it as a socket.

- #bind_tls(host : String, port : Int32, context : OpenSSL::SSL::Context::Server, reuse_port : Bool = false) : Socket::IPAddress

  Creates an `OpenSSL::SSL::Server` and adds it as a socket.

- #bind_tls(host : String, context : OpenSSL::SSL::Context::Server) : Socket::IPAddress

  Creates an `OpenSSL::SSL::Server` and adds it as a socket.

- #bind_unix(path : String) : Socket::UNIXAddress

  Creates a `UNIXServer` bound to path and adds it as a socket.

- #bind_unix(address : Socket::UNIXAddress) : Socket::UNIXAddress

  Creates a `UNIXServer` bound to address and adds it as a socket.

- #bind_unused_port(host : String = "127.0.0.1", reuse_port : Bool = false) : Socket::IPAddress

  Creates a `TCPServer` listening on an unused port and adds it as a socket.

- #close

  Gracefully terminates the server.

- #closed? : Bool

  Returns `true` if 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 `TCPServer` listenting on `127.0.0.1:port`, adds it as a socket and starts the server.

- #listen(host : String, port : Int32, reuse_port : Bool = false)

  Creates a `TCPServer` listenting on `host:port`, adds it as a socket and starts the server.

- #listen

  Starts the server.

- #listening? : Bool

  Returns `true` if this server is listening on it's sockets.

### Instance methods inherited from class `Reference`

==(other : self)
==(other : JSON::Any)
==(other : YAML::Any)
==(other) ==, dup dup, hash(hasher) hash, inspect(io : IO) : Nil inspect, object_id : UInt64 object_id, pretty_print(pp) : Nil pretty_print, same?(other : Reference)
same?(other : Nil) same?, to_s(io : IO) : Nil to_s

### Constructor methods inherited from class `Reference`

new new

### Instance methods inherited from class `Object`

!=(other) !=, !~(other) !~, ==(other) ==, ===(other : JSON::Any)
===(other : YAML::Any)
===(other) ===, =~(other) =~, class class, dup dup, hash(hasher)
hash hash, inspect(io : IO)
inspect inspect, itself itself, not_nil! not_nil!, pretty_inspect(width = 79, newline = "\n", indent = 0) : String pretty_inspect, pretty_print(pp : PrettyPrint) : Nil pretty_print, tap(&block) tap, to_json(io : IO)
to_json to_json, to_pretty_json(indent : String = " ")
to_pretty_json(io : IO, indent : String = " ") to_pretty_json, to_s
to_s(io : IO) to_s, to_yaml(io : IO)
to_yaml to_yaml, try(&block) try, unsafe_as(type : T.class) forall T unsafe_as

### Constructor methods inherited from class `Object`

from_json(string_or_io, root : String) : self
from_json(string_or_io) : self from_json, from_yaml(string_or_io : String | IO) : self from_yaml

## Constructor Detail

def self.new(handlers : Array(HTTP::Handler), &handler : HTTP::Handler::HandlerProc) : self #

Creates a new HTTP server with a handler chain constructed from the handlers array and the given block.

def self.new(&handler : HTTP::Handler::HandlerProc) : self #

Creates a new HTTP server with the given block as handler.

def self.new(handlers : Array(HTTP::Handler)) : self #

Creates a new HTTP server with the handlers array as handler chain.

def self.new(handler : HTTP::Handler | HTTP::Handler::HandlerProc) #

Creates a new HTTP server with the given handler.

## Class Method Detail

def self.build_middleware(handlers, last_handler : Context -> ? = nil) #

Builds all handlers as the middleware for `HTTP::Server`.

## Instance Method Detail

def addresses : Array(Socket::Address) #
def bind(socket : Socket::Server) : Nil #

Adds a `Socket::Server` socket to this server.

def bind(uri : String) : Socket::Address #

Parses a socket configuration from uri and adds it to this server. Returns the effective address it is bound to.

    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)

def bind(uri : URI) : Socket::Address #

Parses a socket configuration from uri and adds it to this server. Returns the effective address it is bound to.

    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)

def bind_ssl(*args) #

DEPRECATED Use `#bind_tls`.

TODO remove in 0.27.0

def bind_tcp(host : String, port : Int32, reuse_port : Bool = false) : Socket::IPAddress #

Creates a `TCPServer` listenting on `host:port` and adds it as a socket, returning the local address and port the server listens on.

    server = HTTP::Server.new { }
    server.bind_tcp("127.0.0.100", 8080) # => Socket::IPAddress.new("127.0.0.100", 8080)

If reuse_port is `true`, it enables the `SO_REUSEPORT` socket option, which allows multiple processes to bind to the same port.

def bind_tcp(port : Int32, reuse_port : Bool = false) : Socket::IPAddress #

Creates a `TCPServer` listenting on `127.0.0.1:port` and adds it as a socket, returning the local address and port the server listens on.

    server = HTTP::Server.new { }
    server.bind_tcp(8080) # => Socket::IPAddress.new("127.0.0.1", 8080)

If reuse_port is `true`, it enables the `SO_REUSEPORT` socket option, which allows multiple processes to bind to the same port.

def bind_tcp(address : Socket::IPAddress, reuse_port : Bool = false) : Socket::IPAddress #

Creates a `TCPServer` listenting on address and adds it as a socket, returning the local address and port the server listens on.

    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)

If reuse_port is `true`, it enables the `SO_REUSEPORT` socket option, which allows multiple processes to bind to the same port.

def bind_tls(address : Socket::IPAddress, context : OpenSSL::SSL::Context::Server) : Socket::IPAddress #

Creates an `OpenSSL::SSL::Server` and adds it as a socket.

The SSL server wraps a `TCPServer` listenting on an unused port on host.

    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

def bind_tls(host : String, port : Int32, context : OpenSSL::SSL::Context::Server, reuse_port : Bool = false) : Socket::IPAddress #

Creates an `OpenSSL::SSL::Server` and adds it as a socket.

The SSL server wraps a `TCPServer` listenting on `host:port`.

    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

def bind_tls(host : String, context : OpenSSL::SSL::Context::Server) : Socket::IPAddress #

Creates an `OpenSSL::SSL::Server` and adds it as a socket.

The SSL server wraps a `TCPServer` listenting on an unused port on host.

    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

def bind_unix(path : String) : Socket::UNIXAddress #

Creates a `UNIXServer` bound to path and adds it as a socket.

    server = HTTP::Server.new { }
    server.bind_unix "/tmp/my-socket.sock"

def bind_unix(address : Socket::UNIXAddress) : Socket::UNIXAddress #

Creates a `UNIXServer` bound to address and adds it as a socket.

    server = HTTP::Server.new { }
    server.bind_unix(Socket::UNIXAddress.new("/tmp/my-socket.sock"))

def bind_unused_port(host : String = "127.0.0.1", reuse_port : Bool = false) : Socket::IPAddress #

Creates a `TCPServer` listening on an unused port and adds it as a socket.

Returns the `Socket::IPAddress` with the determined port number.

    server = HTTP::Server.new { }
    server.bind_unused_port # => Socket::IPAddress.new("127.0.0.1", 12345)

def close #

Gracefully terminates the server. It will process currently accepted requests, but it won't accept new connections.

def closed? : Bool #

Returns `true` if this server is closed.

def each_address(&block : Socket::Address -> ) #

Enumerates all addresses this server is bound to.

def listen(port : Int32, reuse_port : Bool = false) #

Creates a `TCPServer` listenting on `127.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.

def listen(host : String, port : Int32, reuse_port : Bool = false) #

Creates a `TCPServer` listenting on `host:port`, adds it as a socket and starts the server. Blocks until the server is closed.

See `#bind(host : String, port : Int32)` for details.

def listen #

Starts the server. Blocks until the server is closed.

def listening? : Bool #

Returns `true` if this server is listening on it's sockets.