Interface pour les serveurs, frameworks et clients HTTP.
Voir raxx.kit pour un générateur de projet qui vous aide à configurer un projet Web basé sur Raxx / ACE.
defmodule MyServer do
use Raxx.SimpleServer
@ impl Raxx.SimpleServer
def handle_request ( % { method: :GET , path: [ ] } , _state ) do
response ( :ok )
|> set_header ( "content-type" , "text/plain" )
|> set_body ( "Hello, World!" )
end
def handle_request ( % { method: :GET , path: _ } , _state ) do
response ( :not_found )
|> set_header ( "content-type" , "text/plain" )
|> set_body ( "Oops! Nothing here." )
end
endGET / a un chemin [] . Pour démarrer un serveur Raxx, un serveur HTTP compatible est nécessaire. Cet exemple utilise ACE qui peut servir à la fois HTTP / 1 et HTTP / 2.
raxx_server = { MyServer , nil }
http_options = [ port: 8080 , cleartext: true ]
{ :ok , pid } = Ace.HTTP.Service . start_link ( raxx_server , http_options )handle_request/2 . Dans cet exemple, il est inutilisé et donc réglé sur nulle.Commencez votre projet et visitez http: // localhost: 8080.
Un échange HTTP implique un client envoyant des données à un serveur recevant une réponse. Une vue simple consiste à modéliser ceci comme un seul message envoyé dans chaque direction. Travailler avec ce modèle correspond aux rappels Raxx.SimpleServer .
request -->
Client ============================================ Server
<-- response Lorsque le modèle simple est insuffisant, Raxx expose un modèle inférieur. Il s'agit d'une série de messages dans chaque direction. Travailler avec ce modèle correspond aux rappels Raxx.Server .
tail | data(1+) | head(request) -->
Client ============================================ Server
<-- head(response) | data(1+) | tail Le serveur LongPoll est avec état. Après avoir reçu une demande complète, ce serveur doit attendre une entrée supplémentaire avant d'envoyer une réponse au client.
defmodule LongPoll do
use Raxx.Server
@ impl Raxx.Server
def handle_head ( % { method: :GET , path: [ "slow" ] } , state ) do
Process . send_after ( self ( ) , :reply , 30_000 )
{ [ ] , state }
end
@ impl Raxx.Server
def handle_info ( :reply , _state ) do
response ( :ok )
|> set_header ( "content-type" , "text/plain" )
|> set_body ( "Hello, Thanks for waiting." )
end
end[] ; et le nouvel état du serveur, dans ce cas, aucun state de changement.initial_state est configuré lorsque le serveur est démarré. Le serveur SubscribeToMessages diffuse sa réponse. Le serveur enverra la tête de la réponse lors de la réception de la demande. Les données sont envoyées au client, dans le cadre du corps, lorsqu'elles deviennent disponibles. La réponse est terminée lorsque le salon de discussion envoie un :closed .
defmodule SubscribeToMessages do
use Raxx.Server
@ impl Raxx.Server
def handle_head ( % { method: :GET , path: [ "messages" ] } , state ) do
{ :ok , _ } = ChatRoom . join ( )
outbound = response ( :ok )
|> set_header ( "content-type" , "text/plain" )
|> set_body ( true )
{ [ outbound ] , state }
end
@ impl Raxx.Server
def handle_info ( { ChatRoom , :closed } , state ) do
outbound = tail ( )
{ [ outbound ] , state }
end
def handle_info ( { ChatRoom , data } , state ) do
outbound = data ( data )
{ [ outbound ] , state }
end
endset_body(true) marque que la réponse a un corps qu'il n'est pas encore connu. Le serveur Upload écrit des données sur un fichier au fur et à mesure de sa reçue. Ce n'est qu'une fois que la demande complète a été reçue est une réponse envoyée.
defmodule Upload do
use Raxx.Server
@ impl Raxx.Server
def handle_head ( % { method: :PUT , path: [ "upload" ] body: true } , _state ) do
{ :ok , io_device } = File . open ( "my/path" )
{ [ ] , { :file , device } }
end
@ impl Raxx.Server
def handle_data ( data , state = { :file , device } ) do
IO . write ( device , data )
{ [ ] , state }
end
@ impl Raxx.Server
def handle_tail ( _trailers , state ) do
response ( :see_other )
|> set_header ( "location" , "/" )
end
endhandle_data sera invoqué à l'arrivée de chaque partie. Une application ne devrait jamais supposer comment un corps sera divisé en parties de données. Il convient de noter quelles garanties sont données sur les pièces de demande transmises aux fonctions handle_* du serveur. Cela dépend du type de serveur, Raxx.Server vs Raxx.SimpleServer :
Ainsi, par exemple, après un %Raxx.Request{body: false} est transmis au rappel c:Raxx.Server.handle_head/2 , aucune autre demande ne sera transmise au serveur ( c:Raxx.Server.handle_info/2 Les messages pourraient être, cependant).
De même, ce sont les séquences valides des pièces de réponse renvoyées des serveurs:
Tous Raxx.Middleware s doivent suivre la même logique.
Le Raxx.Router peut être utilisé pour faire correspondre les demandes à des modules de serveur spécifiques.
defmodule MyApp do
use Raxx.Server
use Raxx.Router , [
{ % { method: :GET , path: [ ] } , HomePage } ,
{ % { method: :GET , path: [ "slow" ] } , LongPoll } ,
{ % { method: :GET , path: [ "messages" ] } , SubscribeToMessages } ,
{ % { method: :PUT , path: [ "upload" ] } , Upload } ,
{ _ , NotFoundPage }
]
end