Skip to content

Commit

Permalink
Improve HTTP::Server docs
Browse files Browse the repository at this point in the history
  • Loading branch information
straight-shoota committed Jan 2, 2019
1 parent 66e02d0 commit d153fcc
Showing 1 changed file with 70 additions and 52 deletions.
122 changes: 70 additions & 52 deletions src/http/server.cr
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,10 @@ require "./common"
require "openssl"
{% end %}

# An HTTP server.
# A concurrent HTTP server implementation.
#
# 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.
# A server is initialized with a handler chain responsible for processing each
# incoming request.
#
# ```
# require "http/server"
Expand All @@ -39,12 +21,27 @@ require "./common"
# context.response.print "Hello world!"
# end
#
# server.bind_tcp 8080
# puts "Listening on http://127.0.0.1:8080"
# address = server.bind_tcp 8080
# puts "Listening on http://#{address}"
# server.listen
# ```
#
# ### With non-localhost bind address
# ## Binding to sockets
#
# The server can be bound to one ore more server sockets (see )
#
# 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 an `URI`. This can be useful for injecting plain text
# configuration values.
#
# Each of these methods returns the `Socket::Address` that was added to this
# server.
#
# ```
# require "http/server"
Expand All @@ -54,14 +51,45 @@ require "./common"
# context.response.print "Hello world!"
# end
#
# server.bind_tcp "0.0.0.0", 8080
# puts "Listening on http://0.0.0.0:8080"
# address = server.bind_tcp "0.0.0.0", 8080
# puts "Listening on http:/#{address}"
# server.listen
# ```
#
# ### Add handlers
# It is also possible to bind a generic `Socket::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 like `sleep 10.seconds` after `#listen` returns.
#
# ## Request processing
#
# The handler chain receives an instance of `HTTP::Server::Context` that holds
# the `HTTP::Request` to process and a `HTTP::Server::Response` which it can
# configure and write to.
#
# A series of handlers are chained.
# Each connection is processed concurrently in a separate `Fiber` 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 an `HTTP::Server::Context`,
# or it can be an instance of `HTTP::Handler`. An `HTTP::Handler` has an optional
# `#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 a `500 Server Error` status (see `HTTP::ErrorHandler`).
# The next handler might log all incoming requests (see `HTTP::LogHandler`).
# And the final handler deals with routing and application logic.
#
# ```
# require "http/server"
Expand All @@ -77,24 +105,14 @@ require "./common"
# server.listen
# ```
#
# ### Add handlers and block
#
# A series of handlers is chained, the last one being the given block.
# ### Response object
#
# ```
# 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
# The `HTTP::Server::Response` object has `status` and `headers` properties that can be
# configured before writing the response body. Once any response output has been
# written, changing the `status` and `headers` properties has no effect.
#
# server.bind_tcp "0.0.0.0", 8080
# server.listen
# ```
# The `HTTP::Server::Response` is a write-only `IO`, so all `IO` methods are available
# on it for sending the response body.
class HTTP::Server
@sockets = [] of Socket::Server

Expand Down Expand Up @@ -125,7 +143,7 @@ class HTTP::Server
@processor = RequestProcessor.new(handler)
end

# Creates a `TCPServer` listenting on `host:port` and adds it as a socket, returning the local address
# Creates a `TCPServer` listening on `host:port` and adds it as a socket, returning the local address
# and port the server listens on.
#
# ```
Expand All @@ -143,7 +161,7 @@ class HTTP::Server
tcp_server.local_address
end

# Creates a `TCPServer` listenting on `127.0.0.1:port` and adds it as a socket,
# Creates a `TCPServer` listening on `127.0.0.1:port` and adds it as a socket,
# returning the local address and port the server listens on.
#
# ```
Expand All @@ -157,7 +175,7 @@ class HTTP::Server
bind_tcp Socket::IPAddress::LOOPBACK, port, reuse_port
end

# Creates a `TCPServer` listenting on *address* and adds it as a socket, returning the local address
# Creates a `TCPServer` listening on *address* and adds it as a socket, returning the local address
# and port the server listens on.
#
# ```
Expand Down Expand Up @@ -211,7 +229,7 @@ class HTTP::Server
{% unless flag?(:without_openssl) %}
# Creates an `OpenSSL::SSL::Server` and adds it as a socket.
#
# The SSL server wraps a `TCPServer` listenting on `host:port`.
# The SSL server wraps a `TCPServer` listening on `host:port`.
#
# ```
# server = HTTP::Server.new { }
Expand All @@ -231,7 +249,7 @@ class HTTP::Server

# Creates an `OpenSSL::SSL::Server` and adds it as a socket.
#
# The SSL server wraps a `TCPServer` listenting on an unused port on *host*.
# The SSL server wraps a `TCPServer` listening on an unused port on *host*.
#
# ```
# server = HTTP::Server.new { }
Expand All @@ -246,7 +264,7 @@ class HTTP::Server

# Creates an `OpenSSL::SSL::Server` and adds it as a socket.
#
# The SSL server wraps a `TCPServer` listenting on an unused port on *host*.
# The SSL server wraps a `TCPServer` listening on an unused port on *host*.
#
# ```
# server = HTTP::Server.new { }
Expand Down Expand Up @@ -317,7 +335,7 @@ class HTTP::Server
array
end

# Creates a `TCPServer` listenting on `127.0.0.1:port`, adds it as a socket
# Creates a `TCPServer` listening 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.
Expand All @@ -327,7 +345,7 @@ class HTTP::Server
listen
end

# Creates a `TCPServer` listenting on `host:port`, adds it as a socket
# Creates a `TCPServer` listening 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.
Expand Down

0 comments on commit d153fcc

Please sign in to comment.