AMPHP adalah kumpulan pustaka berbasis peristiwa untuk PHP yang dirancang dengan mempertimbangkan serat dan konkurensi. Paket ini menyediakan server aplikasi HTTP/1.1 dan HTTP/2 yang non-pemblokiran dan bersamaan untuk PHP berdasarkan Revolt. Beberapa fitur disediakan dalam paket terpisah, seperti komponen WebSocket.
Paket ini dapat diinstal sebagai ketergantungan Komposer.
composer require amphp/http-server
Selain itu, Anda mungkin ingin menginstal perpustakaan nghttp2
untuk memanfaatkan FFI guna mempercepat dan mengurangi penggunaan memori.
Pustaka ini menyediakan akses ke aplikasi Anda melalui protokol HTTP, menerima permintaan klien dan meneruskan permintaan tersebut ke penangan yang ditentukan oleh aplikasi Anda yang akan mengembalikan respons.
Permintaan yang masuk diwakili oleh objek Request
. Permintaan diberikan kepada pelaksana RequestHandler
, yang mendefinisikan metode handleRequest()
yang mengembalikan instance Response
.
public function handleRequest( Request $ request ): Response
Penangan permintaan dibahas secara lebih rinci di bagian RequestHandler
.
Server HTTP ini dibangun di atas event-loop Revolt dan kerangka konkurensi non-pemblokiran Amp. Oleh karena itu, ia mewarisi dukungan penuh dari semua primitifnya dan dimungkinkan untuk menggunakan semua perpustakaan non-pemblokiran yang dibangun di atas Revolt.
Catatan Secara umum, Anda harus membiasakan diri dengan konsep
Future
, dengan coroutine, dan mengetahui beberapa fungsi kombinator agar benar-benar berhasil dalam menggunakan server HTTP.
Hampir setiap fungsi bawaan PHP melakukan pemblokiran I/O, artinya, thread yang menjalankan (kebanyakan setara dengan proses dalam kasus PHP) akan dihentikan secara efektif hingga respons diterima. Beberapa contoh fungsi tersebut: mysqli_query
, file_get_contents
, usleep
dan masih banyak lagi.
Aturan praktis yang baik adalah: Setiap fungsi PHP bawaan yang melakukan I/O melakukannya dengan cara memblokir, kecuali Anda tahu pasti hal itu tidak terjadi.
Ada perpustakaan yang menyediakan implementasi yang menggunakan I/O non-pemblokiran. Anda harus menggunakan ini alih-alih fungsi bawaan.
Kami memenuhi kebutuhan I/O yang paling umum, seperti soket jaringan, akses file, permintaan HTTP dan soket web, klien database MySQL dan Postgres, serta Redis. Jika penggunaan pemblokiran I/O atau komputasi yang panjang diperlukan untuk memenuhi permintaan, pertimbangkan untuk menggunakan pustaka Paralel untuk menjalankan kode tersebut dalam proses atau thread terpisah.
Peringatan Jangan gunakan fungsi pemblokiran I/O apa pun di server 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.
Aplikasi Anda akan dilayani oleh instance HttpServer
. Pustaka ini menyediakan SocketHttpServer
, yang cocok untuk sebagian besar aplikasi, dibangun berdasarkan komponen yang ditemukan di pustaka ini dan di amphp/socket
.
Untuk membuat instance SocketHttpServer
dan mendengarkan permintaan, diperlukan minimal empat hal:
RequestHandler
untuk merespons permintaan masuk,ErrorHander
untuk memberikan respons terhadap permintaan yang tidak valid,PsrLogLoggerInterface
, dan <?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 ();
Contoh di atas membuat server sederhana yang mengirimkan respons teks biasa untuk setiap permintaan yang diterima.
SocketHttpServer
menyediakan dua konstruktor statis untuk kasus penggunaan umum selain konstruktor normal untuk penggunaan lebih lanjut dan khusus.
SocketHttpServer::createForDirectAccess()
: Digunakan pada contoh di atas, ini akan membuat server aplikasi HTTP yang cocok untuk akses jaringan langsung. Batasan yang dapat disesuaikan diterapkan pada koneksi per IP, total koneksi, dan permintaan bersamaan (masing-masing 10, 1000, dan 1000 secara default). Kompresi respons dapat diaktifkan atau dinonaktifkan (diaktifkan secara default) dan metode permintaan dibatasi pada kumpulan kata kerja HTTP yang diketahui secara default.SocketHttpServer::createForBehindProxy()
: Membuat server yang sesuai untuk digunakan saat berada di belakang layanan proxy seperti nginx. Konstruktor statis ini memerlukan daftar IP proksi tepercaya (dengan subnet mask opsional) dan kasus enum ForwardedHeaderType
(sesuai dengan Forwarded
atau X-Forwarded-For
) untuk mengurai IP klien asli dari header permintaan. Tidak ada batasan yang dikenakan pada jumlah koneksi ke server, namun jumlah permintaan bersamaan dibatasi (1000 secara default, dapat disesuaikan atau dihapus). Kompresi respons dapat diaktifkan atau dinonaktifkan (diaktifkan secara default). Metode permintaan terbatas pada sekumpulan kata kerja HTTP yang diketahui secara default. Jika tidak satu pun dari metode ini memenuhi kebutuhan aplikasi Anda, konstruktor SocketHttpServer
dapat digunakan secara langsung. Hal ini memberikan fleksibilitas yang sangat besar dalam cara pembuatan dan penanganan koneksi masuk koneksi klien, namun akan memerlukan lebih banyak kode untuk membuatnya. Konstruktor mengharuskan pengguna untuk meneruskan instance SocketServerFactory
, yang digunakan untuk membuat instance Socket
klien (keduanya komponen perpustakaan amphp/socket
), dan instance ClientFactory
, yang dengan tepat membuat instance Client
yang dilampirkan ke setiap Request
yang dibuat oleh klien .
RequestHandler
Permintaan yang masuk diwakili oleh objek Request
. Permintaan diberikan kepada pelaksana RequestHandler
, yang mendefinisikan metode handleRequest()
yang mengembalikan instance Response
.
public function handleRequest( Request $ request ): Response
Setiap permintaan klien (yaitu, panggilan ke RequestHandler::handleRequest()
) dieksekusi dalam coroutine terpisah sehingga permintaan secara otomatis ditangani secara kooperatif dalam proses server. Ketika penangan permintaan menunggu pada I/O non-pemblokiran, permintaan klien lainnya diproses dalam coroutine secara bersamaan. Penangan permintaan Anda sendiri dapat membuat coroutine lain menggunakan Ampasync()
untuk menjalankan beberapa tugas dalam satu permintaan.
Biasanya RequestHandler
langsung menghasilkan respons, namun mungkin juga didelegasikan ke RequestHandler
lain. Contoh pendelegasian RequestHandler
adalah Router
.
Antarmuka RequestHandler
dimaksudkan untuk diimplementasikan oleh kelas khusus. Untuk kasus penggunaan yang sangat sederhana atau tiruan cepat, Anda dapat menggunakan CallableRequestHandler
, yang dapat menggabungkan callable
apa pun dan menerima Request
serta mengembalikan Response
.
Middleware memungkinkan pra-pemrosesan permintaan dan pasca-pemrosesan tanggapan. Selain itu, middleware juga dapat mencegat pemrosesan permintaan dan mengembalikan respons tanpa mendelegasikan ke penangan permintaan yang diteruskan. Kelas harus mengimplementasikan antarmuka Middleware
untuk itu.
Catatan Middleware umumnya mengikuti kata lain seperti perangkat lunak dan perangkat keras dengan bentuk jamak. Namun, kami menggunakan istilah middlewares untuk merujuk pada beberapa objek yang mengimplementasikan antarmuka
Middleware
.
public function handleRequest( Request $ request , RequestHandler $ next ): Response
handleRequest
adalah satu-satunya metode antarmuka Middleware
. Jika Middleware
tidak menangani permintaan itu sendiri, ia harus mendelegasikan pembuatan respons ke RequestHandler
yang diterima.
function stackMiddleware( RequestHandler $ handler , Middleware ... $ middleware ): RequestHandler
Beberapa middleware dapat ditumpuk dengan menggunakan AmpHttpServerMiddlewarestackMiddleware()
, yang menerima RequestHandler
sebagai argumen pertama dan sejumlah variabel instance Middleware
. RequestHandler
yang dikembalikan akan memanggil setiap middleware dalam urutan yang disediakan.
$ 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
digunakan oleh server HTTP ketika permintaan yang salah format atau tidak valid diterima. Objek Request
disediakan jika dibuat dari data yang masuk, tetapi mungkin tidak selalu disetel.
public function handleError(
int $ status ,
? string $ reason = null ,
? Request $ request = null ,
): Response
Pustaka ini menyediakan DefaultErrorHandler
yang mengembalikan halaman HTML bergaya sebagai isi respons. Anda mungkin ingin memberikan implementasi yang berbeda untuk aplikasi Anda, yang mungkin menggunakan beberapa implementasi bersama dengan router.
Request
Jarang sekali Anda perlu membuat objek Request
sendiri, karena objek tersebut biasanya disediakan ke RequestHandler::handleRequest()
oleh server.
/**
* @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
Mengembalikan Сlient
yang mengirimkan permintaan
public function getMethod(): string
Mengembalikan metode HTTP yang digunakan untuk membuat permintaan ini, misalnya "GET"
.
public function setMethod( string $ method ): void
Menetapkan metode HTTP permintaan.
public function getUri(): Psr Http Message UriInterface
Mengembalikan URI
permintaan.
public function setUri( Psr Http Message UriInterface $ uri ): void
Menetapkan URI
baru untuk permintaan tersebut.
public function getProtocolVersion(): string
Mengembalikan versi protokol HTTP sebagai string (misalnya "1.0", "1.1", "2").
public function setProtocolVersion( string $ protocol )
Menetapkan nomor versi protokol baru untuk permintaan tersebut.
/** @return array<non-empty-string, list<string>> */
public function getHeaders(): array
Mengembalikan header sebagai array yang diindeks string dari array string atau array kosong jika tidak ada header yang disetel.
public function hasHeader( string $ name ): bool
Memeriksa apakah header yang diberikan ada.
/** @return list<string> */
public function getHeaderArray( string $ name ): array
Mengembalikan array nilai untuk header tertentu atau array kosong jika header tidak ada.
public function getHeader( string $ name ): ? string
Mengembalikan nilai header yang diberikan. Jika ada beberapa header untuk header bernama, hanya nilai header pertama yang akan dikembalikan. Gunakan getHeaderArray()
untuk mengembalikan array berisi semua nilai untuk header tertentu. Mengembalikan null
jika header tidak ada.
public function setHeaders( array $ headers ): void
Mengatur header dari array yang diberikan.
/** @param array<string>|string $value */
public function setHeader( string $ name , array | string $ value ): void
Menyetel header ke nilai yang diberikan. Semua baris header sebelumnya dengan nama yang diberikan akan diganti.
/** @param array<string>|string $value */
public function addHeader( string $ name , array | string $ value ): void
Menambahkan baris header tambahan dengan nama yang diberikan.
public function removeHeader( string $ name ): void
Menghapus header yang diberikan jika ada. Jika ada beberapa baris header dengan nama yang sama, semuanya akan dihapus.
public function getBody(): RequestBody
Mengembalikan isi permintaan. RequestBody
memungkinkan akses streaming dan buffered ke InputStream
.
public function setBody( ReadableStream | string $ body )
Menyetel aliran untuk isi pesan
Catatan Menggunakan string akan secara otomatis mengatur header
Content-Length
dengan panjang string yang diberikan. MenyetelReadableStream
akan menghapus headerContent-Length
. Jika Anda mengetahui persis panjang konten streaming Anda, Anda dapat menambahkan headercontent-length
setelah memanggilsetBody()
.
/** @return array<non-empty-string, RequestCookie> */
public function getCookies(): array
Mengembalikan semua cookie dalam peta asosiatif nama cookie ke RequestCookie
.
public function getCookie( string $ name ): ? RequestCookie
Mendapatkan nilai cookie berdasarkan nama atau null
.
public function setCookie( RequestCookie $ cookie ): void
Menambahkan Cookie
ke permintaan.
public function removeCookie( string $ name ): void
Menghapus cookie dari permintaan.
public function getAttributes(): array
Mengembalikan larik semua atribut yang disimpan dalam penyimpanan lokal permintaan yang dapat diubah.
public function removeAttributes(): array
Menghapus semua atribut permintaan dari penyimpanan lokal permintaan yang dapat diubah.
public function hasAttribute( string $ name ): bool
Periksa apakah atribut dengan nama tertentu ada di penyimpanan lokal permintaan yang dapat diubah.
public function getAttribute( string $ name ): mixed
Ambil variabel dari penyimpanan lokal permintaan yang dapat diubah.
Catatan Nama atribut harus diberi namespace dengan vendor dan namespace paket, seperti kelas.
public function setAttribute( string $ name , mixed $ value ): void
Tetapkan variabel ke penyimpanan lokal permintaan yang dapat diubah.
Catatan Nama atribut harus diberi namespace dengan vendor dan namespace paket, seperti kelas.
public function removeAttribute( string $ name ): void
Menghapus variabel dari penyimpanan lokal permintaan yang dapat diubah.
public function getTrailers(): Trailers
Mengizinkan akses ke Trailers
permintaan.
public function setTrailers( Trailers $ trailers ): void
Menetapkan objek Trailers
untuk digunakan dalam permintaan.
Detail terkait klien digabungkan ke dalam objek AmpHttpServerDriverClient
yang dikembalikan dari Request::getClient()
. Antarmuka Client
menyediakan metode untuk mengambil alamat soket jarak jauh dan lokal serta info TLS (jika berlaku).
Response
Kelas Response
mewakili respons HTTP. Response
dikembalikan oleh penangan permintaan dan middleware.
/**
* @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 ,
)
Memanggil penangan pembuangan (yaitu fungsi yang didaftarkan melalui metode onDispose()
).
Catatan Pengecualian yang tidak tertangkap dari penangan pembuangan akan diteruskan ke penangan kesalahan perulangan peristiwa.
public function getBody(): Amp ByteStream ReadableStream
Mengembalikan aliran untuk isi pesan.
public function setBody( Amp ByteStream ReadableStream | string $ body )
Menyetel aliran untuk isi pesan.
Catatan Menggunakan string akan secara otomatis mengatur header
Content-Length
dengan panjang string yang diberikan. MenyetelReadableStream
akan menghapus headerContent-Length
. Jika Anda mengetahui persis panjang konten streaming Anda, Anda dapat menambahkan headercontent-length
setelah memanggilsetBody()
.
/** @return array<non-empty-string, list<string>> */
public function getHeaders(): array
Mengembalikan header sebagai array yang diindeks string dari array string atau array kosong jika tidak ada header yang disetel.
public function hasHeader( string $ name ): bool
Memeriksa apakah header yang diberikan ada.
/** @return list<string> */
public function getHeaderArray( string $ name ): array
Mengembalikan array nilai untuk header tertentu atau array kosong jika header tidak ada.
public function getHeader( string $ name ): ? string
Mengembalikan nilai header yang diberikan. Jika ada beberapa header untuk header bernama, hanya nilai header pertama yang akan dikembalikan. Gunakan getHeaderArray()
untuk mengembalikan array berisi semua nilai untuk header tertentu. Mengembalikan null
jika header tidak ada.
public function setHeaders( array $ headers ): void
Mengatur header dari array yang diberikan.
/** @param array<string>|string $value */
public function setHeader( string $ name , array | string $ value ): void
Menyetel header ke nilai yang diberikan. Semua baris header sebelumnya dengan nama yang diberikan akan diganti.
/** @param array<string>|string $value */
public function addHeader( string $ name , array | string $ value ): void
Menambahkan baris header tambahan dengan nama yang diberikan.
public function removeHeader( string $ name ): void
Menghapus header yang diberikan jika ada. Jika ada beberapa baris header dengan nama yang sama, semuanya akan dihapus.
public function getStatus(): int
Mengembalikan kode status respons.
public function getReason(): string
Mengembalikan frasa alasan yang menjelaskan kode status.
public function setStatus( int $ code , string | null $ reason ): void
Menetapkan kode status HTTP numerik (antara 100 dan 599) dan frasa alasan. Gunakan null sebagai frase alasan untuk menggunakan frase default yang terkait dengan kode status.
/** @return array<non-empty-string, ResponseCookie> */
public function getCookies(): array
Mengembalikan semua cookie dalam peta asosiatif nama cookie ke ResponseCookie
.
public function getCookie( string $ name ): ? ResponseCookie
Mendapatkan nilai cookie berdasarkan nama atau null
jika tidak ada cookie dengan nama tersebut.
public function setCookie( ResponseCookie $ cookie ): void
Menambahkan cookie ke respons.
public function removeCookie( string $ name ): void
Menghapus cookie dari respons.
/** @return array<string, Push> Map of URL strings to Push objects. */
public function getPushes(): array
Mengembalikan daftar sumber daya push dalam peta asosiatif string URL ke objek Push
.
/** @param array<string>|array<string, array<string>> $headers */
public function push( string $ url , array $ headers ): void
Tunjukkan sumber daya yang mungkin perlu diambil oleh klien. (misalnya Link: preload
atau HTTP/2 Server Push).
public function isUpgraded(): bool
Mengembalikan true
jika panggilan balik pelepasan telah disetel, false
jika tidak ada.
/** @param Closure(DriverUpgradedSocket, Request, Response): void $upgrade */
public function upgrade( Closure $ upgrade ): void
Menyetel panggilan balik yang akan dipanggil setelah respons ditulis ke klien dan mengubah status respons menjadi 101 Switching Protocols
. Callback menerima instance DriverUpgradedSocket
, Request
yang memulai pemutakhiran, dan Response
ini.
Panggilan balik dapat dihapus dengan mengubah status menjadi selain 101.
public function getUpgradeCallable(): ? Closure
Mengembalikan fungsi peningkatan jika ada.
/** @param Closure():void $onDispose */
public function onDispose( Closure $ onDispose ): void
Mendaftarkan fungsi yang dipanggil ketika Respons dibuang. Respons akan dibuang setelah ditulis ke klien atau jika diganti dalam rantai middleware.
public function getTrailers(): Trailers
Mengizinkan akses ke Trailers
respons.
public function setTrailers( Trailers $ trailers ): void
Menetapkan objek Trailers
untuk digunakan dalam respons. Cuplikan dikirim setelah seluruh isi respons ditetapkan ke klien.
RequestBody
, yang dikembalikan dari Request::getBody()
, menyediakan akses buffered dan streaming ke isi permintaan. Gunakan akses streaming untuk menangani pesan berukuran besar, yang sangat penting jika Anda memiliki batas pesan yang lebih besar (seperti puluhan megabyte) dan tidak ingin melakukan buffering semuanya di memori. Jika beberapa orang mengunggah gambar berukuran besar secara bersamaan, memori mungkin akan cepat habis.
Oleh karena itu, penanganan bertahap sangatlah penting, dapat diakses melalui API read()
dari AmpByteStreamReadableStream
.
Jika klien terputus, read()
gagal dengan AmpHttpServerClientException
. Pengecualian ini diberikan untuk API read()
dan buffer()
.
Catatan
ClientException
s tidak perlu ditangkap. Anda dapat menangkapnya jika ingin melanjutkan, tetapi tidak harus. Server akan secara diam-diam mengakhiri siklus permintaan dan kemudian membuang pengecualian itu.
Daripada menetapkan batas isi umum tinggi, Anda harus mempertimbangkan untuk meningkatkan batas isi hanya jika diperlukan, yang secara dinamis dapat dilakukan dengan metode increaseSizeLimit()
pada RequestBody
.
Catatan
RequestBody
sendiri tidak menyediakan penguraian data formulir. Anda dapat menggunakanamphp/http-server-form-parser
jika Anda membutuhkannya.
Seperti Request
, jarang sekali perlu membuat instance RequestBody
karena instance tersebut akan disediakan sebagai bagian dari Request
.
public function __construct(
ReadableStream | string $ stream ,
? Closure $ upgradeSize = null ,
)
public function increaseSizeLimit( int $ limit ): void
Meningkatkan batas ukuran isi secara dinamis untuk memungkinkan penangan permintaan individual menangani isi permintaan yang lebih besar daripada set default untuk server HTTP.
Kelas Trailers
mengizinkan akses ke cuplikan permintaan HTTP, dapat diakses melalui Request::getTrailers()
. null
dikembalikan jika cuplikan tidak diharapkan berdasarkan permintaan. Trailers::await()
mengembalikan Future
yang diselesaikan dengan objek HttpMessage
yang menyediakan metode untuk mengakses header trailer.
$ trailers = $ request -> getTrailers ();
$ message = $ trailers ?->await();
Server HTTP tidak akan menjadi hambatan. Kesalahan konfigurasi, penggunaan pemblokiran I/O, atau aplikasi yang tidak efisien.
Server ini dioptimalkan dengan baik dan dapat menangani puluhan ribu permintaan per detik pada perangkat keras biasa sambil mempertahankan tingkat konkurensi yang tinggi pada ribuan klien.
Namun kinerja tersebut akan menurun drastis jika aplikasi tidak efisien. Server memiliki keuntungan yang bagus karena kelas dan penangannya selalu dimuat, sehingga tidak ada waktu yang terbuang saat kompilasi dan inisialisasi.
Jebakan yang umum terjadi adalah mulai mengoperasikan data besar dengan operasi string sederhana, yang memerlukan banyak salinan besar yang tidak efisien. Sebaliknya, streaming harus digunakan jika memungkinkan untuk badan permintaan dan respons yang lebih besar.
Masalahnya sebenarnya adalah biaya CPU. Manajemen I/O yang tidak efisien (selama tidak memblokir!) hanya menunda permintaan individual. Disarankan untuk mengirimkan secara bersamaan dan pada akhirnya menggabungkan beberapa permintaan I/O independen melalui kombinator Amp, namun penangan yang lambat juga akan memperlambat setiap permintaan lainnya. Saat satu penangan sedang melakukan komputasi, semua penangan lainnya tidak dapat melanjutkan. Oleh karena itu, sangat penting untuk mengurangi waktu komputasi penangan ke minimum.
Beberapa contoh dapat ditemukan di direktori ./examples
repositori. Ini dapat dijalankan seperti skrip PHP biasa pada baris perintah.
php examples/hello-world.php
Anda kemudian dapat mengakses server contoh di http://localhost:1337/
di browser Anda.
Jika Anda menemukan masalah apa pun terkait keamanan, harap gunakan pelapor masalah keamanan pribadi daripada menggunakan pelacak masalah publik.
Lisensi MIT (MIT). Silakan lihat LISENSI untuk informasi lebih lanjut.