-
Notifications
You must be signed in to change notification settings - Fork 26
Description
Certain applications require knowledge of the connection and not just the HTTP message that was sent. For example inspecting a client ssl certificate or blacklisting particular ip addresses.
Adding this to the request is not desirable because:
1 it conflates the transport information with the HTTP protocol
2 The request struct sent by the client should be identical to the request struct handled by the server. Assuming both client and server use Raxx.
3 It is also possible to have HTTP without a connection. Mailing Requests and Responses would work if anyone wanted to do that.
Option 1
Ace could have an entry in the process dictionary of the worker. The ace module could the expose several reader functions that work only in the context of a worker.
defmodule MyApp do
def handle_request(_request, _state) do
peer_ip = Ace.peer_ip()
response(:ok)
end
endSomewhat ugly to use the process dictionary, however as all exposed functions are for derived properties the cannot be used to cause side effects.
Option 2
handle_request/2 (and all other callbacks) can have a handle_request/3 partner that takes request, channel, state with the default behaviour to fallback to the arity 2 implementation.
The downside of this approach is raxx is understanding both HTTP and some concept of the transport layer. e.g. would the channel object be an Ace.Connection or a Raxx.Connection.
Option 3
A server specific callback for connecting. e.g.
defmodule MyApp do
use Ace.HTTP.Service, [port: 8080]
@impl Ace.HTTP.Server
def connect(channel, config) do # 1.
Logger.metadata(client_ip: channel.ip)
{:ok, config}
end
@impl Raxx.Server
def handle_request(_request, _state) do
response(:ok)
end
endAdvantages this gives people an answer to what does init look like, it's replaced with connect.
There is a choice at 1. do we pass a connection or channel object. if channel then no error case should stop the complete connection, but the callback is executed in the same process as the handle_*. If connection then its only executed once for potentially many requests. but it would be possible to use it to stop the connection. i.e. blacklisted ips