AMPHP عبارة عن مجموعة من المكتبات المستندة إلى الأحداث لـ PHP والمصممة مع وضع الألياف والتزامن في الاعتبار. توفر هذه الحزمة خادم تطبيقات HTTP/1.1 وHTTP/2 متزامن غير محظور لـ PHP استنادًا إلى Revolt. يتم توفير العديد من الميزات في حزم منفصلة، مثل مكون WebSocket.
يمكن تثبيت هذه الحزمة باعتبارها تبعية للملحن.
composer require amphp/http-server
بالإضافة إلى ذلك، قد ترغب في تثبيت مكتبة nghttp2
للاستفادة من FFI لتسريع وتقليل استخدام الذاكرة.
توفر هذه المكتبة إمكانية الوصول إلى التطبيق الخاص بك من خلال بروتوكول HTTP، وقبول طلبات العميل وإعادة توجيه تلك الطلبات إلى المعالجات التي يحددها تطبيقك والتي ستقوم بإرجاع استجابة.
يتم تمثيل الطلبات الواردة بواسطة كائنات Request
. يتم تقديم طلب لمنفذ RequestHandler
، والذي يحدد طريقة handleRequest()
التي تعيد مثيل Response
.
public function handleRequest( Request $ request ): Response
يتم تناول معالجات الطلب بمزيد من التفصيل في قسم RequestHandler
.
تم إنشاء خادم HTTP هذا فوق حلقة أحداث Revolt وإطار عمل التزامن غير المحظور Amp. وبالتالي فإنه يرث الدعم الكامل لجميع البدائيين ومن الممكن استخدام جميع المكتبات غير المحظورة المبنية على رأس Revolt.
ملاحظة : بشكل عام، يجب أن تتعرف على مفهوم
Future
، مع coroutines، وأن تكون على دراية بالوظائف المجمعة المتعددة لتنجح حقًا في استخدام خادم HTTP.
تقريبًا كل وظيفة مدمجة في PHP تقوم بحظر الإدخال/الإخراج، وهذا يعني أن سلسلة التنفيذ (التي تعادل في الغالب العملية في حالة PHP) سيتم إيقافها بشكل فعال حتى يتم تلقي الاستجابة. بعض الأمثلة على هذه الوظائف: mysqli_query
و file_get_contents
و usleep
وغيرها الكثير.
القاعدة الأساسية الجيدة هي: كل وظيفة PHP مضمنة تقوم بالإدخال/الإخراج تقوم بذلك بطريقة محظورة، إلا إذا كنت متأكدًا من أنها لا تفعل ذلك.
توجد مكتبات توفر تطبيقات تستخدم الإدخال/الإخراج غير المحظور. يجب عليك استخدام هذه بدلاً من الوظائف المضمنة.
نحن نغطي احتياجات الإدخال/الإخراج الأكثر شيوعًا، مثل مآخذ الشبكة والوصول إلى الملفات وطلبات HTTP ومآخذ الويب وعملاء قاعدة بيانات MySQL وPostgres وRedis. إذا كان استخدام حظر الإدخال/الإخراج أو الحسابات الطويلة ضروريًا لتلبية الطلب، ففكر في استخدام المكتبة المتوازية لتشغيل هذا الرمز في عملية أو مؤشر ترابط منفصل.
تحذير لا تستخدم أي وظائف إدخال/إخراج محظورة في خادم HTTP.
// Here's a bad example, DO NOT do something like the following!
$ handler = new ClosureRequestHandler ( function () {
sleep ( 5 ); // Equivalent to a blocking I/O function with a 5 second timeout
return new Response ;
});
// Start a server with this handler and hit it twice.
// You'll have to wait until the 5 seconds are over until the second request is handled.
سيتم تقديم طلبك من خلال مثيل HttpServer
. توفر هذه المكتبة SocketHttpServer
، الذي سيكون مناسبًا لمعظم التطبيقات، والمبني على المكونات الموجودة في هذه المكتبة وفي amphp/socket
.
لإنشاء مثيل لـ SocketHttpServer
والاستماع للطلبات، يلزم وجود أربعة أشياء على الأقل:
RequestHandler
للرد على الطلبات الواردة،ErrorHander
لتقديم استجابات للطلبات غير الصالحة،PsrLogLoggerInterface
و <?php
use Amp ByteStream ;
use Amp Http HttpStatus ;
use Amp Http Server DefaultErrorHandler ;
use Amp Http Server Request ;
use Amp Http Server RequestHandler ;
use Amp Http Server Response ;
use Amp Http Server SocketHttpServer ;
use Amp Log ConsoleFormatter ;
use Amp Log StreamHandler ;
use Monolog Logger ;
use Monolog Processor PsrLogMessageProcessor ;
require __DIR__ . ' /vendor/autoload.php ' ;
// Note any PSR-3 logger may be used, Monolog is only an example.
$ logHandler = new StreamHandler ( ByteStream getStdout ());
$ logHandler -> pushProcessor ( new PsrLogMessageProcessor ());
$ logHandler -> setFormatter ( new ConsoleFormatter ());
$ logger = new Logger ( ' server ' );
$ logger -> pushHandler ( $ logHandler );
$ requestHandler = new class () implements RequestHandler {
public function handleRequest ( Request $ request ) : Response
{
return new Response (
status: HttpStatus:: OK ,
headers: [ ' Content-Type ' => ' text/plain ' ],
body: ' Hello, world! ' ,
);
}
};
$ errorHandler = new DefaultErrorHandler ();
$ server = SocketHttpServer:: createForDirectAccess ( $ logger );
$ server -> expose ( ' 127.0.0.1:1337 ' );
$ server -> start ( $ requestHandler , $ errorHandler );
// Serve requests until SIGINT or SIGTERM is received by the process.
Amp trapSignal ([ SIGINT , SIGTERM ]);
$ server -> stop ();
ينشئ المثال أعلاه خادمًا بسيطًا يرسل استجابة نصية عادية لكل طلب يتم تلقيه.
يوفر SocketHttpServer
منشئين ثابتين لحالات الاستخدام الشائعة بالإضافة إلى المنشئ العادي لاستخدامات أكثر تقدمًا ومخصصة.
SocketHttpServer::createForDirectAccess()
: يُستخدم في المثال أعلاه، ويؤدي إلى إنشاء خادم تطبيق HTTP مناسب للوصول المباشر إلى الشبكة. يتم فرض حدود قابلة للتعديل على الاتصالات لكل عنوان IP، وإجمالي الاتصالات، والطلبات المتزامنة (10، و1000، و1000 بشكل افتراضي، على التوالي). قد يتم تشغيل أو إيقاف ضغط الاستجابة (تشغيل افتراضيًا) وتقتصر أساليب الطلب على مجموعة معروفة من أفعال HTTP افتراضيًا.SocketHttpServer::createForBehindProxy()
: ينشئ خادمًا مناسبًا للاستخدام عندما يكون خلف خدمة وكيل مثل nginx. يتطلب هذا المُنشئ الثابت قائمة بعناوين IP للوكيل الموثوق بها (مع أقنعة شبكة فرعية اختيارية) وحالة تعداد من ForwardedHeaderType
(المتوافقة مع Forwarded
أو X-Forwarded-For
) لتحليل عنوان IP الأصلي للعميل من رؤوس الطلب. لا توجد حدود مفروضة على عدد الاتصالات بالخادم، ولكن عدد الطلبات المتزامنة محدود (1000 بشكل افتراضي، قابل للتعديل أو يمكن إزالته). قد يتم تشغيل أو إيقاف تشغيل ضغط الاستجابة (يتم تشغيله بشكل افتراضي). تقتصر أساليب الطلب على مجموعة معروفة من أفعال HTTP افتراضيًا. إذا لم تخدم أي من هذه الطرق احتياجات التطبيق الخاص بك، فقد يتم استخدام مُنشئ SocketHttpServer
مباشرة. يوفر هذا قدرًا هائلاً من المرونة في كيفية إنشاء اتصالات العميل الواردة والتعامل معها، ولكنه سيتطلب المزيد من التعليمات البرمجية لإنشائها. يتطلب المنشئ من المستخدم تمرير مثيل لـ SocketServerFactory
، المستخدم لإنشاء مثيلات Socket
العميل (كلا المكونين لمكتبة amphp/socket
)، ومثيل ClientFactory
، الذي ينشئ بشكل مناسب مثيلات Client
المرتبطة بكل Request
يقدمه العميل .
RequestHandler
يتم تمثيل الطلبات الواردة بواسطة كائنات Request
. يتم تقديم طلب لمنفذ RequestHandler
، والذي يحدد طريقة handleRequest()
التي تعيد مثيل Response
.
public function handleRequest( Request $ request ): Response
يتم تنفيذ كل طلب عميل (على سبيل المثال، استدعاء RequestHandler::handleRequest()
) ضمن روتين منفصل بحيث تتم معالجة الطلبات تلقائيًا بشكل تعاوني ضمن عملية الخادم. عندما ينتظر معالج الطلب إدخال/إخراج غير محظور، تتم معالجة طلبات العميل الأخرى في إجراءات متزامنة. قد يقوم معالج الطلب الخاص بك بنفسه بإنشاء كوروتينات أخرى باستخدام Ampasync()
لتنفيذ مهام متعددة لطلب واحد.
عادةً ما يقوم RequestHandler
بإنشاء استجابة مباشرة، ولكن قد يتم تفويضه أيضًا إلى RequestHandler
آخر. مثال على تفويض RequestHandler
هذا هو Router
.
من المفترض أن يتم تنفيذ واجهة RequestHandler
بواسطة فئات مخصصة. بالنسبة لحالات الاستخدام البسيطة جدًا أو الاستهزاء السريع، يمكنك استخدام CallableRequestHandler
، والذي يمكنه تغليف أي callable
وقبول Request
وإرجاع Response
.
تسمح البرامج الوسيطة بالمعالجة المسبقة للطلبات والمعالجة اللاحقة للاستجابات. بصرف النظر عن ذلك، يمكن للبرامج الوسيطة أيضًا اعتراض معالجة الطلب وإرجاع الاستجابة دون تفويض معالج الطلب الذي تم تمريره. يجب على الفصول تنفيذ واجهة Middleware
لذلك.
ملاحظة: تتبع البرامج الوسيطة عمومًا كلمات أخرى مثل soft- و hardware بصيغة الجمع. ومع ذلك، فإننا نستخدم مصطلح البرامج الوسيطة للإشارة إلى كائنات متعددة تنفذ واجهة
Middleware
.
public function handleRequest( Request $ request , RequestHandler $ next ): Response
handleRequest
هي الطريقة الوحيدة لواجهة Middleware
. إذا لم يتعامل Middleware
مع الطلب بنفسه، فيجب عليه تفويض إنشاء الاستجابة إلى RequestHandler
المستلم.
function stackMiddleware( RequestHandler $ handler , Middleware ... $ middleware ): RequestHandler
يمكن تكديس البرامج الوسيطة المتعددة باستخدام AmpHttpServerMiddlewarestackMiddleware()
، الذي يقبل RequestHandler
كوسيطة أولى وعدد متغير من مثيلات Middleware
. سوف يستدعي RequestHandler
الذي تم إرجاعه كل البرامج الوسيطة بالترتيب المقدم.
$ requestHandler = new class implements RequestHandler {
public function handleRequest ( Request $ request ): Response
{
return new Response (
status: HttpStatus:: OK ,
headers: [ " content-type " => " text/plain; charset=utf-8 " ],
body: " Hello, World! " ,
);
}
}
$ middleware = new class implements Middleware {
public function handleRequest ( Request $ request , RequestHandler $ next ): Response
{
$ requestTime = microtime ( true );
$ response = $ next -> handleRequest ( $ request );
$ response -> setHeader ( " x-request-time " , microtime ( true ) - $ requestTime );
return $ response ;
}
};
$ stackedHandler = Middleware stackMiddleware ( $ requestHandler , $ middleware );
$ errorHandler = new DefaultErrorHandler ();
// $logger is a PSR-3 logger instance.
$ server = SocketHttpServer:: createForDirectAccess ( $ logger );
$ server -> expose ( ' 127.0.0.1:1337 ' );
$ server -> start ( $ stackedHandler , $ errorHandler );
ErrorHandler
يتم استخدام ErrorHander
بواسطة خادم HTTP عند تلقي طلب غير صحيح أو غير صالح. يتم توفير كائن Request
إذا تم إنشاؤه من البيانات الواردة، ولكن قد لا يتم تعيينه دائمًا.
public function handleError(
int $ status ,
? string $ reason = null ,
? Request $ request = null ,
): Response
توفر هذه المكتبة DefaultErrorHandler
الذي يقوم بإرجاع صفحة HTML منمقة كنص الاستجابة. قد ترغب في توفير تطبيق مختلف لتطبيقك، ومن المحتمل استخدام عدة تطبيقات مع جهاز توجيه.
Request
من النادر أن تحتاج إلى إنشاء كائن Request
بنفسك، حيث سيتم توفيره عادةً إلى RequestHandler::handleRequest()
بواسطة الخادم.
/**
* @param string $method The HTTP method verb.
* @param array<string>|array<string, array<string>> $headers An array of strings or an array of string arrays.
*/
public function __construct(
private readonly Client $ client ,
string $ method ,
Psr Http Message UriInterface $ uri ,
array $ headers = [],
Amp ByteStream ReadableStream | string $ body = '' ,
private string $ protocol = ' 1.1 ' ,
? Trailers $ trailers = null ,
)
public function getClient(): Client
إرجاع Сlient
الذي يرسل الطلب
public function getMethod(): string
إرجاع طريقة HTTP المستخدمة لتقديم هذا الطلب، على سبيل المثال "GET"
.
public function setMethod( string $ method ): void
يضبط طريقة طلب HTTP.
public function getUri(): Psr Http Message UriInterface
إرجاع URI
للطلب.
public function setUri( Psr Http Message UriInterface $ uri ): void
يقوم بتعيين URI
جديد للطلب.
public function getProtocolVersion(): string
إرجاع إصدار بروتوكول HTTP كسلسلة (على سبيل المثال، "1.0"، "1.1"، "2").
public function setProtocolVersion( string $ protocol )
يقوم بتعيين رقم إصدار بروتوكول جديد للطلب.
/** @return array<non-empty-string, list<string>> */
public function getHeaders(): array
يُرجع الرؤوس كمصفوفة من صفائف السلاسل مفهرسة بسلسلة أو مصفوفة فارغة إذا لم يتم تعيين أي رؤوس.
public function hasHeader( string $ name ): bool
يتحقق من وجود رأس معين.
/** @return list<string> */
public function getHeaderArray( string $ name ): array
إرجاع مصفوفة القيم للرأس المحدد أو إرجاع مصفوفة فارغة إذا كان الرأس غير موجود.
public function getHeader( string $ name ): ? string
إرجاع قيمة الرأس المحدد. في حالة وجود رؤوس متعددة للرأس المحدد، سيتم إرجاع قيمة الرأس الأولى فقط. استخدم getHeaderArray()
لإرجاع مصفوفة من كافة القيم لرأس معين. يُرجع null
إذا كان الرأس غير موجود.
public function setHeaders( array $ headers ): void
يضبط الرؤوس من المصفوفة المحددة.
/** @param array<string>|string $value */
public function setHeader( string $ name , array | string $ value ): void
يضبط الرأس على القيمة (القيم) المحددة. سيتم استبدال جميع سطور الرأس السابقة بالاسم المحدد.
/** @param array<string>|string $value */
public function addHeader( string $ name , array | string $ value ): void
يضيف سطر رأس إضافي بالاسم المحدد.
public function removeHeader( string $ name ): void
يزيل الرأس المحدد إذا كان موجودًا. في حالة وجود عدة أسطر رأس بنفس الاسم، تتم إزالتها جميعًا.
public function getBody(): RequestBody
إرجاع نص الطلب. يسمح RequestBody
بالوصول المتدفق والمخزن إلى InputStream
.
public function setBody( ReadableStream | string $ body )
يضبط الدفق لنص الرسالة
ملاحظة: سيؤدي استخدام سلسلة إلى تعيين رأس
Content-Length
تلقائيًا على طول السلسلة المحددة. سيؤدي تعيينReadableStream
إلى إزالة رأسContent-Length
. إذا كنت تعرف طول المحتوى الدقيق للبث الخاص بك، فيمكنك إضافة رأسcontent-length
بعد استدعاءsetBody()
.
/** @return array<non-empty-string, RequestCookie> */
public function getCookies(): array
إرجاع كافة ملفات تعريف الارتباط في الخريطة الترابطية لاسم ملف تعريف الارتباط إلى RequestCookie
.
public function getCookie( string $ name ): ? RequestCookie
يحصل على قيمة ملف تعريف الارتباط بالاسم أو null
.
public function setCookie( RequestCookie $ cookie ): void
يضيف Cookie
إلى الطلب.
public function removeCookie( string $ name ): void
إزالة ملف تعريف الارتباط من الطلب.
public function getAttributes(): array
تقوم بإرجاع مصفوفة من كافة السمات المخزنة في وحدة التخزين المحلية القابلة للتغيير للطلب.
public function removeAttributes(): array
يزيل كافة سمات الطلب من وحدة التخزين المحلية القابلة للتغيير للطلب.
public function hasAttribute( string $ name ): bool
تحقق من وجود سمة بالاسم المحدد في وحدة التخزين المحلية القابلة للتغيير للطلب.
public function getAttribute( string $ name ): mixed
استرداد متغير من التخزين المحلي القابل للتغيير للطلب.
ملاحظة: يجب أن يكون اسم السمة مزودًا بمساحة اسم البائع والحزمة، مثل الفئات.
public function setAttribute( string $ name , mixed $ value ): void
قم بتعيين متغير للتخزين المحلي القابل للتغيير للطلب.
ملاحظة: يجب أن يكون اسم السمة مزودًا بمساحة اسم البائع والحزمة، مثل الفئات.
public function removeAttribute( string $ name ): void
إزالة متغير من وحدة التخزين المحلية القابلة للتغيير للطلب.
public function getTrailers(): Trailers
يسمح بالوصول إلى Trailers
الطلب.
public function setTrailers( Trailers $ trailers ): void
يعين كائن Trailers
لاستخدامه في الطلب.
يتم تجميع التفاصيل المتعلقة بالعميل في كائنات AmpHttpServerDriverClient
التي يتم إرجاعها من Request::getClient()
. توفر واجهة Client
طرقًا لاسترداد عناوين مآخذ التوصيل البعيدة والمحلية ومعلومات TLS (إن أمكن).
Response
تمثل فئة Response
استجابة HTTP. يتم إرجاع Response
بواسطة معالجات الطلب والبرمجيات الوسيطة.
/**
* @param int $code The HTTP response status code.
* @param array<string>|array<string, array<string>> $headers An array of strings or an array of string arrays.
*/
public function __construct(
int $ code = HttpStatus:: OK ,
array $ headers = [],
Amp ByteStream ReadableStream | string $ body = '' ,
? Trailers $ trailers = null ,
)
يستدعي معالجات التخلص (أي الوظائف التي تم تسجيلها عبر طريقة onDispose()
).
ملاحظة ستتم إعادة توجيه الاستثناءات التي لم يتم اكتشافها من معالجات التخلص إلى معالج أخطاء حلقة الحدث.
public function getBody(): Amp ByteStream ReadableStream
إرجاع الدفق لنص الرسالة.
public function setBody( Amp ByteStream ReadableStream | string $ body )
يضبط الدفق لنص الرسالة.
ملاحظة: سيؤدي استخدام سلسلة إلى تعيين رأس
Content-Length
تلقائيًا على طول السلسلة المحددة. سيؤدي تعيينReadableStream
إلى إزالة رأسContent-Length
. إذا كنت تعرف طول المحتوى الدقيق للبث الخاص بك، فيمكنك إضافة رأسcontent-length
بعد استدعاءsetBody()
.
/** @return array<non-empty-string, list<string>> */
public function getHeaders(): array
يُرجع الرؤوس كمصفوفة من صفائف السلاسل مفهرسة بسلسلة أو مصفوفة فارغة إذا لم يتم تعيين أي رؤوس.
public function hasHeader( string $ name ): bool
يتحقق من وجود رأس معين.
/** @return list<string> */
public function getHeaderArray( string $ name ): array
إرجاع مصفوفة القيم للرأس المحدد أو إرجاع مصفوفة فارغة إذا كان الرأس غير موجود.
public function getHeader( string $ name ): ? string
إرجاع قيمة الرأس المحدد. في حالة وجود رؤوس متعددة للرأس المحدد، سيتم إرجاع قيمة الرأس الأولى فقط. استخدم getHeaderArray()
لإرجاع مصفوفة من كافة القيم لرأس معين. يُرجع null
إذا كان الرأس غير موجود.
public function setHeaders( array $ headers ): void
يضبط الرؤوس من المصفوفة المحددة.
/** @param array<string>|string $value */
public function setHeader( string $ name , array | string $ value ): void
يضبط الرأس على القيمة (القيم) المحددة. سيتم استبدال جميع سطور الرأس السابقة بالاسم المحدد.
/** @param array<string>|string $value */
public function addHeader( string $ name , array | string $ value ): void
يضيف سطر رأس إضافي بالاسم المحدد.
public function removeHeader( string $ name ): void
يزيل الرأس المحدد إذا كان موجودًا. في حالة وجود عدة أسطر رأس بنفس الاسم، تتم إزالتها جميعًا.
public function getStatus(): int
إرجاع رمز حالة الاستجابة.
public function getReason(): string
إرجاع عبارة السبب التي تصف رمز الحالة.
public function setStatus( int $ code , string | null $ reason ): void
يضبط رمز حالة HTTP الرقمي (بين 100 و599) وعبارة السبب. استخدم null لعبارة السبب لاستخدام العبارة الافتراضية المرتبطة برمز الحالة.
/** @return array<non-empty-string, ResponseCookie> */
public function getCookies(): array
إرجاع كافة ملفات تعريف الارتباط في خريطة ارتباطية لاسم ملف تعريف الارتباط إلى ResponseCookie
.
public function getCookie( string $ name ): ? ResponseCookie
يحصل على قيمة ملف تعريف الارتباط بالاسم أو null
في حالة عدم وجود ملف تعريف ارتباط بهذا الاسم.
public function setCookie( ResponseCookie $ cookie ): void
يضيف ملف تعريف الارتباط إلى الاستجابة.
public function removeCookie( string $ name ): void
إزالة ملف تعريف الارتباط من الاستجابة.
/** @return array<string, Push> Map of URL strings to Push objects. */
public function getPushes(): array
إرجاع قائمة بموارد الدفع في خريطة ترابطية لسلاسل URL لكائنات Push
.
/** @param array<string>|array<string, array<string>> $headers */
public function push( string $ url , array $ headers ): void
قم بالإشارة إلى الموارد التي من المحتمل أن يحتاج العميل إلى جلبها. (على سبيل المثال Link: preload
أو دفع خادم HTTP/2).
public function isUpgraded(): bool
يُرجع true
إذا تم تعيين رد اتصال منفصل، false
إذا لم يكن هناك شيء.
/** @param Closure(DriverUpgradedSocket, Request, Response): void $upgrade */
public function upgrade( Closure $ upgrade ): void
يضبط رد الاتصال ليتم استدعاؤه بمجرد كتابة الاستجابة للعميل ويغير حالة الاستجابة إلى 101 Switching Protocols
. يتلقى رد الاتصال مثيل DriverUpgradedSocket
، Request
الذي بدأ الترقية، وهذه Response
.
قد تتم إزالة رد الاتصال عن طريق تغيير الحالة إلى شيء آخر غير 101.
public function getUpgradeCallable(): ? Closure
إرجاع وظيفة الترقية إذا كانت موجودة.
/** @param Closure():void $onDispose */
public function onDispose( Closure $ onDispose ): void
يسجل وظيفة يتم استدعاؤها عند تجاهل الاستجابة. يتم تجاهل الاستجابة إما بمجرد كتابتها للعميل أو إذا تم استبدالها في سلسلة البرامج الوسيطة.
public function getTrailers(): Trailers
يسمح بالوصول إلى Trailers
الاستجابة.
public function setTrailers( Trailers $ trailers ): void
يقوم بتعيين كائن Trailers
لاستخدامه في الاستجابة. يتم إرسال المقطورات بمجرد تعيين نص الاستجابة بالكامل للعميل.
يوفر RequestBody
، الذي تم إرجاعه من Request::getBody()
، وصولاً مخزّنًا ومتدفقًا إلى نص الطلب. استخدم الوصول المتدفق للتعامل مع الرسائل الكبيرة، وهو أمر مهم بشكل خاص إذا كان لديك حدود أكبر للرسائل (مثل عشرات الميغابايت) ولا تريد تخزينها كلها في الذاكرة مؤقتًا. إذا قام عدة أشخاص بتحميل أجسام كبيرة في وقت واحد، فقد يتم استنفاد الذاكرة بسرعة.
ومن ثم، تعد المعالجة المتزايدة أمرًا مهمًا، ويمكن الوصول إليها عبر واجهة برمجة تطبيقات read()
الخاصة بـ AmpByteStreamReadableStream
.
في حالة قطع اتصال العميل، تفشل read()
مع AmpHttpServerClientException
. تم طرح هذا الاستثناء لكل من واجهة برمجة التطبيقات read()
و buffer()
.
ملاحظة: لا يلزم اكتشاف
ClientException
. يمكنك اللحاق بهم إذا كنت تريد الاستمرار، ولكن لا داعي لذلك. سينهي الخادم دورة الطلب بصمت ويتجاهل هذا الاستثناء بعد ذلك.
بدلًا من تعيين حد عام للنص مرتفعًا، يجب أن تفكر في زيادة حد النص فقط عند الحاجة، وهو أمر ممكن ديناميكيًا باستخدام طريقة increaseSizeLimit()
في RequestBody
.
ملاحظة: لا يوفر
RequestBody
نفسه تحليلًا لبيانات النموذج. يمكنك استخدامamphp/http-server-form-parser
إذا كنت في حاجة إليها.
كما هو الحال مع Request
، من النادر الحاجة إلى إنشاء مثيل RequestBody
حيث سيتم توفيره كجزء من Request
.
public function __construct(
ReadableStream | string $ stream ,
? Closure $ upgradeSize = null ,
)
public function increaseSizeLimit( int $ limit ): void
يزيد حد حجم النص ديناميكيًا للسماح لمعالجات الطلبات الفردية بمعالجة نصوص الطلبات الأكبر حجمًا من المجموعة الافتراضية لخادم HTTP.
تسمح فئة Trailers
بالوصول إلى المقطورات الخاصة بطلب HTTP، ويمكن الوصول إليها عبر Request::getTrailers()
. يتم إرجاع null
إذا لم يكن من المتوقع وجود مقطورات عند الطلب. تُرجع Trailers::await()
Future
الذي تم حله باستخدام كائن HttpMessage
الذي يوفر طرقًا للوصول إلى رؤوس المقطورات.
$ trailers = $ request -> getTrailers ();
$ message = $ trailers ?->await();
لن يكون خادم HTTP هو عنق الزجاجة. التكوين الخاطئ، أو استخدام حظر الإدخال/الإخراج، أو التطبيقات غير الفعالة.
تم تحسين الخادم بشكل جيد ويمكنه التعامل مع عشرات الآلاف من الطلبات في الثانية على الأجهزة النموذجية مع الحفاظ على مستوى عالٍ من التزامن لآلاف العملاء.
لكن هذا الأداء سينخفض بشكل كبير مع التطبيقات غير الفعالة. يتمتع الخادم بميزة رائعة تتمثل في تحميل الفئات والمعالجات دائمًا، لذلك لا يوجد وقت ضائع في التجميع والتهيئة.
الفخ الشائع هو البدء في العمل على البيانات الضخمة من خلال عمليات سلسلة بسيطة، مما يتطلب العديد من النسخ الكبيرة غير الفعالة. وبدلاً من ذلك، يجب استخدام البث حيثما أمكن ذلك لهيئات الطلب والاستجابة الأكبر حجمًا.
المشكلة حقا هي تكلفة وحدة المعالجة المركزية. إن إدارة الإدخال/الإخراج غير الفعالة (طالما أنها غير محظورة!) تؤدي فقط إلى تأخير الطلبات الفردية. يوصى بإرسال طلبات الإدخال/الإخراج المستقلة المتعددة في وقت واحد وفي النهاية تجميعها عبر أدوات تجميع Amp، ولكن المعالج البطيء سيبطئ كل الطلبات الأخرى أيضًا. أثناء قيام معالج واحد بالحوسبة، لا يمكن لجميع المعالجات الأخرى الاستمرار. وبالتالي فمن الضروري تقليل أوقات حساب المعالجات إلى الحد الأدنى.
يمكن العثور على عدة أمثلة في دليل ./examples
الخاص بالمستودع. يمكن تنفيذها كنصوص PHP عادية في سطر الأوامر.
php examples/hello-world.php
يمكنك بعد ذلك الوصول إلى خادم المثال على http://localhost:1337/
في متصفحك.
إذا اكتشفت أي مشكلات متعلقة بالأمان، فيرجى استخدام مراسل المشكلات الأمنية الخاص بدلاً من استخدام أداة تعقب المشكلات العامة.
رخصة معهد ماساتشوستس للتكنولوجيا (MIT). يرجى الاطلاع على الترخيص لمزيد من المعلومات.