ace v0.13.1 Ace.HTTP2.Service View Source
Run a supervised tree of HTTP/2.0 servers, all available on a single port.
The task associated with each client request is processed by an application level worker. To start workers a module and start arguments are required.
For example, given {MyProject.WWW, ["foo"]}
, Ace will start workers by executing the following.
MyProject.WWW.start_link("foo")
Example application:
defmodule MyProject.WWW do
use GenServer
alias Ace.HTTP2.Server
def start_link(greeting) do
GenServer.start_link(__MODULE__, greeting)
end
def handle_info({stream, %Ace.Request{method: :GET, path: "/"}}, greeting) do
response = Ace.Response.new(200, [], greeting)
Server.send_response(stream, response)
{:stop, greeting, :normal}
end
def handle_info({stream, _request}, greeting) do
response = Ace.Response.new(404, [], false)
Server.send_response(stream, response)
{:stop, greeting, :normal}
end
end
- See
Ace.HTTP2.Server
for all functionality available to a stream worker. - See
Ace.Raxx.Handler
for help with a concise stream worker.
This module has a start_link/1
function and so can be started by as a service as follows.
application = {MyProject.WWW, ["Hello, World!"]}
options = [
port: 8443,
certfile: "path/to/certfile"
keyfile: "path/to/keyfile"
]
{:ok, pid} = Ace.HTTP2.Service.start_link(application, options)
- See
start_link/2
for the full list of options available when starting a service
Each client request defines an independant stream. Each stream is handled by an isolated worker process running the application.
Supervising services
Ace makes it easy to start multiple services in a single Mix project. Starting a service returns the service supervisor.
This supervisor may act as the application supervisor if it is the only one started.
defmodule MyProject.Application do
@moduledoc false
use Application
def start(_type, _args) do
certfile = Application.app_dir(:my_project, "/priv/cert.pem")
keyfile = Application.app_dir(:my_project, "/priv/key.pem")
Ace.HTTP2.Service.start_link(
{MyProject.WWW, ["Hello, World!"]},
port: 8443,
certfile: certfile,
keyfile: keyfile
)
end
end
An Ace.HTTP2.Service
can also exist as one of a group of supervisors.
defmodule MyProject.Application do
@moduledoc false
use Application
def start(_type, _args) do
import Supervisor.Spec, warn: false
www_certfile = Application.app_dir(:my_project, "/priv/www/cert.pem")
www_keyfile = Application.app_dir(:my_project, "/priv/www/key.pem")
www_app = {MyProject.WWW, ["Hello, World!"]}
www_opts = [port: 8443, certfile: www_certfile, keyfile: www_keyfile]
api_certfile = Application.app_dir(:my_project, "/priv/api/cert.pem")
api_keyfile = Application.app_dir(:my_project, "/priv/api/key.pem")
api_app = {MyProject.WWW, ["Hello, World!"]}
api_opts = [port: 8443, certfile: api_certfile, keyfile: api_keyfile]
children = [
supervisor(Ace.HTTP2.Service, [www_app, www_opts]),
supervisor(Ace.HTTP2.Service, [api_app, api_opts]),
worker(MyProject.worker, [arg1, arg2, arg3]),
]
end
end
Testing endpoints
Starting a service on port 0
will rely on the operating system to allocate an available port.
This allows services to be stood up for individual tests, perhaps all with different configuration.
To find the port that a service has started using a process may be given as the optional owner. Once the service has started the owner receives a message with format.
{:listening, service_pid, port}
This can be used to setup test services.
opts = [port: 0, owner: self(), certfile: certfile, keyfile: keyfile]
assert {:ok, service} = Service.start_link({TestApp, [:test_config]}, opts)
assert_receive {:listening, ^service, port}
# Use general purpose client libraries to test service available at `port`
This can be seen in action in the test directories of this project.
Link to this section Summary
Functions
Start an endpoint to accept HTTP/2.0 connections
Link to this section Functions
Start an endpoint to accept HTTP/2.0 connections