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). يرجى الاطلاع على الترخيص لمزيد من المعلومات.