HTTP网络服务器,框架和客户端的接口。
有关项目生成器,请参见RAXX.KIT,该项目生成器可帮助您基于RAXX/ACE设置Web项目。
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回调。在此示例中,它没有使用,因此将其设置为零。开始您的项目并访问http:// localhost:8080。
HTTP Exchange涉及客户将数据发送到接收响应的服务器。一个简单的视图是将其建模为以每个方向发送的单个消息。使用此模型对应于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 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