HTTP Webサーバー、フレームワーク、クライアントのインターフェイス。
RAXX/ACEに基づいてWebプロジェクトをセットアップするのに役立つプロジェクトジェネレーターについては、Raxx.kitを参照してください。
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 /持っているリクエスト[] 。 RAXXサーバーを起動するには、互換性のあるHTTPサーバーが必要です。この例では、HTTP/1とHTTP/2の両方を提供できるACEを使用しています。
raxx_server = { MyServer , nil }
http_options = [ port: 8080 , cleartext: true ]
{ :ok , pid } = Ace.HTTP.Service . start_link ( raxx_server , http_options )handle_request/2コールバックの2番目の引数として渡されます。この例では、使用されていないので、ゼロに設定されています。プロジェクトを開始し、http:// localhost:8080にアクセスしてください。
HTTP交換には、応答を受信するサーバーにデータを送信するクライアントが含まれます。簡単なビューは、これを各方向に送信した単一のメッセージとしてモデル化することです。このモデルでの作業は、 Raxx.SimpleServerコールバックに対応しています。
request -->
Client ============================================ Server
<-- response単純なモデルが不十分な場合、Raxxはより低いモデルを公開します。これは、各方向の一連のメッセージで構成されています。このモデルでの作業は、 Raxx.Serverコールバックに対応しています。
tail | data(1+) | head(request) -->
Client ============================================ Server
<-- head(response) | data(1+) | tailLongPollサーバーはステートフルです。完全なリクエストを受信した後、このサーバーはクライアントに応答を送信する前に追加の入力を待つ必要があります。
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[] ;そして、サーバーの新しい状態、この場合は変更stateがありません。initial_stateは、サーバーの起動時に構成されます。 SubscribeToMessagesサーバーは、その応答をストリーミングします。サーバーは、リクエストを受信すると応答の責任者を送信します。データが使用可能になったら、ボディの一部としてクライアントに送信されます。チャットルームがa :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)を使用して、応答にはまだ知られていない本体があることをマークします。Uploadサーバーは、受信したときにデータをファイルに書き込みます。完全なリクエストが受信された場合にのみ、返信されます。
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 、各部分が到着すると呼び出されます。アプリケーションは、ボディがどのようにデータパーツに分割されるかを決して想定しないでください。 サーバーのhandle_*関数に渡された要求パーツに保証が与えられるものに注目する価値があります。サーバータイプ、 Raxx.Server vs Raxx.SimpleServerに依存します。
したがって、たとえば、 %Raxx.Request{body: false}サーバーのc:Raxx.Server.handle_head/2コールバックに渡された後、それ以上の要求パーツはサーバーに渡されません( c:Raxx.Server.handle_info/2メッセージはそうかもしれません)。
同様に、これらはサーバーから返された応答パーツの有効なシーケンスです。
Raxx.Middlewareは、同じロジックに従う必要があります。
Raxx.Router使用して、リクエストを特定のサーバーモジュールに一致させることができます。
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