Antarmuka untuk server web, kerangka kerja, dan klien HTTP.
Lihat raxx.kit untuk generator proyek yang membantu Anda mengatur proyek web berdasarkan 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 / memiliki jalur [] . Untuk memulai server raxx, server HTTP yang kompatibel diperlukan. Contoh ini menggunakan ACE yang dapat melayani HTTP/1 dan 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 . Dalam contoh ini tidak digunakan dan diatur ke nol.Mulai proyek Anda dan kunjungi http: // localhost: 8080.
Pertukaran HTTP melibatkan klien yang mengirim data ke server yang menerima respons. Tampilan sederhana adalah untuk memodelkan ini sebagai satu pesan yang dikirim ke setiap arah. Bekerja dengan model ini sesuai dengan callback Raxx.SimpleServer .
request -->
Client ============================================ Server
<-- response Ketika model sederhana tidak mencukupi, Raxx memperlihatkan model yang lebih rendah. Ini terdiri dari serangkaian pesan di setiap arah. Bekerja dengan model ini sesuai dengan callback Raxx.Server .
tail | data(1+) | head(request) -->
Client ============================================ Server
<-- head(response) | data(1+) | tail Server LongPoll stateful. Setelah menerima permintaan lengkap server ini harus menunggu input tambahan sebelum mengirim tanggapan ke klien.
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[] ; dan keadaan baru server, dalam hal ini tidak ada state perubahan.initial_state dikonfigurasi saat server dimulai. Server SubscribeToMessages mengalirkan responsnya. Server akan mengirim kepala respons setelah menerima permintaan. Data dikirim ke klien, sebagai bagian dari tubuh, saat tersedia. Respons selesai ketika ruang obrolan mengirim :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) menandai bahwa respons memiliki tubuh yang belum diketahui. Server Upload menulis data ke file saat diterima. Hanya setelah permintaan lengkap telah diterima adalah tanggapan yang dikirim.
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 akan dipanggil karena setiap bagian tiba. Suatu aplikasi tidak boleh mengasumsikan bagaimana tubuh akan dipecah menjadi bagian data. Perlu dicatat jaminan apa yang diberikan pada bagian permintaan yang diteruskan ke fungsi server handle_* . Itu tergantung pada jenis server, Raxx.Server vs Raxx.SimpleServer :
Jadi, misalnya, setelah %Raxx.Request{body: false} diteruskan ke server c:Raxx.Server.handle_head/2 callback, tidak ada bagian permintaan lebih lanjut yang akan diteruskan ke server ( c:Raxx.Server.handle_info/2 pesan mungkin, meskipun).
Demikian pula, ini adalah urutan yang valid dari bagian respons yang dikembalikan dari server:
Setiap Raxx.Middleware s harus mengikuti logika yang sama.
Raxx.Router dapat digunakan untuk mencocokkan permintaan dengan modul server tertentu.
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