واجهة لخادمات الويب HTTP والأطر والعملاء.
راجع Raxx.kit للحصول على مولد مشروع يساعدك على إعداد مشروع ويب يعتمد على 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 / لديه مسار [] . لبدء خادم Raxx ، هناك حاجة إلى خادم HTTP متوافق. يستخدم هذا المثال ACE الذي يمكن أن يخدم كل من HTTP/1 و 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 . في هذا المثال ، فهو غير مستخدم ويتم تعيينه على شيء.ابدأ مشروعك وزيارة 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 بتدفق استجابته. سيرسل الخادم رأس الاستجابة عند تلقي الطلب. يتم إرسال البيانات إلى العميل ، كجزء من الجسم ، عندما يصبح متاحًا. يتم الانتهاء من الاستجابة عندما ترسل غرفة الدردشة رسالة :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