HTTP 웹 서버, 프레임 워크 및 클라이언트의 인터페이스.
RAXX/ACE를 기반으로 웹 프로젝트를 설정하는 데 도움이되는 프로젝트 생성기는 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 콜백에 대한 두 번째 인수로 전달됩니다. 이 예에서는 사용되지 않아서 nil로 설정됩니다.프로젝트를 시작하고 http : // localhost : 8080을 방문하십시오.
HTTP 교환에는 클라이언트가 응답을 수신하는 서버로 데이터를 전송하는 것이 포함됩니다. 간단한 견해는 이것을 각 방향으로 전송 한 단일 메시지로 모델링하는 것입니다. 이 모델로 작업하면 Raxx.SimpleServer 콜백에 해당합니다.
request -->
Client ============================================ Server
<-- response 간단한 모델이 불충분 한 경우 raxx가 더 낮은 모델을 노출시킵니다. 이것은 각 방향으로 일련의 메시지로 구성됩니다. 이 모델로 작업하면 Raxx.Server 콜백에 해당합니다.
tail | data(1+) | head(request) -->
Client ============================================ Server
<-- head(response) | data(1+) | tail LongPoll 서버는 상태가 있습니다. 완전한 요청을받은 후이 서버는 클라이언트에 응답을 보내기 전에 추가 입력을 기다려야합니다.
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 s는 동일한 논리를 따라야합니다.
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