Встроенный веб-сервер

Внимание

Веб-сервер предназначен для помощи в разработке приложений. Он также может быть полезным в тестовых целях или для демонстрации приложения, запускаемого в полностью контролируемом окружении. Он не выполняет функции полноценного веб-сервера и не должен использоваться в общедоступных сетях.

Модуль CLI SAPI содержит встроенный веб-сервер.

Веб-сервер выполняет только один однопоточный процесс, поэтому приложения PHP будут останавливаться, если запрос заблокирован.

URI-запросы обслуживаются из текущей директории, в которой был запущен PHP, если не используется опция -t для явного указания корневого документа. Если URI запроса не указывает на определённый файл, то будет возвращён index.php или index.html в указанной директории. Если ни один из файлов не существует, то поиск этих файлов будет продолжен в родительской директории и так далее до тех пор, пока они не будут найдены или был достигнут корень документа. Если найден index.php или index.html, он возвращается, а в $_SERVER['PATH_INFO'] будет находится последняя часть URL. В противном случае возвращается 404 код ответа.

Если PHP-файл указывается в командной строке, когда запускается веб-сервер, то он рассматривается как скрипт "маршрутизации" (router). Скрипт выполняется в самом начале каждого HTTP-запроса. Если этот скрипт возвращает false, то запрашиваемый ресурс возвращается как есть. В противном случае браузеру будет возвращён вывод этого скрипта.

Стандартные MIME-типы возвращаются для файлов со следующими расширениями: .3gp, .apk, .avi, .bmp, .css, .csv, .doc, .docx, .flac, .gif, .gz, .gzip, .htm, .html, .ics, .jpe, .jpeg, .jpg, .js, .kml, .kmz, .m4a, .mov, .mp3, .mp4, .mpeg, .mpg, .odp, .ods, .odt, .oga, .ogg, .ogv, .pdf, .png, .pps, .pptx, .qt, .svg, .swf, .tar, .text, .tif, .txt, .wav, .webm, .wmv, .xls, .xlsx, .xml, .xsl, .xsd, .zip .

Начиная с PHP 7.4.0 встроенный веб-сервер можно настроить для разветвления нескольких рабочих процессов для тестирования кода, который требует нескольких одновременных запросов к встроенному веб-серверу. Перед запуском сервера установите для переменной среды PHP_CLI_SERVER_WORKERS количество желаемых рабочих процессов.

Замечание: ОС Windows не поддерживает эту функцию.

Внимание

Эта экспериментальная функция не предназначена для производственного окружения. Обычно встроенный веб-сервер не предназначен для производственного окружения.

Пример #1 Запуск веб-сервера

$ cd ~/public_html
$ php -S localhost:8000

В консоли выведется:

PHP 5.4.0 Development Server started at Thu Jul 21 10:43:28 2011
Listening on localhost:8000
Document root is /home/me/public_html
Press Ctrl-C to quit

После URI-запросов http://localhost:8000/ и http://localhost:8000/myscript.html в консоли выведется примерно следующее:

PHP 5.4.0 Development Server started at Thu Jul 21 10:43:28 2011
Listening on localhost:8000
Document root is /home/me/public_html
Press Ctrl-C to quit.
[Thu Jul 21 10:48:48 2011] ::1:39144 GET /favicon.ico - Request read
[Thu Jul 21 10:48:50 2011] ::1:39146 GET / - Request read
[Thu Jul 21 10:48:50 2011] ::1:39147 GET /favicon.ico - Request read
[Thu Jul 21 10:48:52 2011] ::1:39148 GET /myscript.html - Request read
[Thu Jul 21 10:48:52 2011] ::1:39149 GET /favicon.ico - Request read

Обратите внимание, что до PHP 7.4.0 статические ресурсы с символическими ссылками не были доступны в Windows, если только скрипт маршрутизатора не обработал бы их.

Пример #2 Запуск с указанием корневой директории

$ cd ~/public_html
$ php -S localhost:8000 -t foo/

В консоли выведется:

PHP 5.4.0 Development Server started at Thu Jul 21 10:50:26 2011
Listening on localhost:8000
Document root is /home/me/public_html/foo
Press Ctrl-C to quit

Пример #3 Использование скрипта маршрутизации

В этом примере, запросы изображений будут отображать их, но запросы HTML-файлов будут возвращать "Добро пожаловать в PHP".

<?php

// router.php
if (preg_match('/\.(?:png|jpg|jpeg|gif)$/', $_SERVER["REQUEST_URI"])) {
return
false; // сервер возвращает файлы напрямую.
} else {
echo
"<p>Добро пожаловать в PHP</p>";
}

?>
$ php -S localhost:8000 router.php
Внимание

Встроенный веб-сервер не должен использоваться в общедоступной сети.

Пример #4 Проверка использования веб-сервера CLI

Для совместного использования скрипта маршрутизации при разработке с веб-сервером CLI и в дальнейшем с рабочим (production) веб-сервером:

<?php

// router.php
if (php_sapi_name() == 'cli-server') {
/* Маршрутизация с заданными правилами и возврат false */
}
/* Продолжение с обычными операциями index.php */

?>
$ php -S localhost:8000 router.php

Пример #5 Поддержка неподдерживаемых типов файлов

Если вам нужно обслуживать статические ресурсы с MIME-типами, неподдерживаемыми веб-сервером CLI, используйте это:

<?php

// router.php
$path = pathinfo($_SERVER["SCRIPT_FILENAME"]);
if (
$path["extension"] == "el") {
header("Content-Type: text/x-script.elisp");
readfile($_SERVER["SCRIPT_FILENAME"]);
} else {
return
FALSE;
}

?>
$ php -S localhost:8000 router.php

Пример #6 Доступ к веб-серверу CLI с удалённых машин

Вы можете сделать веб-сервер доступным на 8000 порту для всех сетевых интерфейсов:

$ php -S 0.0.0.0:8000
Добавить

Примечания пользователей 10 notes

up
134
jonathan at reinink dot ca
11 years ago
In order to set project specific configuration options, simply add a php.ini file to your project, and then run the built-in server with this flag:php -S localhost:8000 -c php.iniThis is especially helpful for settings that cannot be set at runtime (ini_set()).
up
74
Mark Simon
9 years ago
It’s not mentioned directly, and may not be obvious, but you can also use this to create a virtual host. This, of course, requires the help of your hosts file.Here are the steps:1    /etc/hosts    127.0.0.1    www.example.com2    cd [root folder]    php -S www.example.com:80003    Browser:    http://www.example.com:8000/index.phpCombined with a simple SQLite database, you have a very handy testing environment.
up
55
oan at vizrt dot com
8 years ago
I painfully experienced behaviour that I can't seem to find documented here so I wanted to save everyone from repeating my mistake by giving the following heads up:When starting php -S on a mac (in my case macOS Sierra) to host a local server, I had trouble with connecting from legacy Java. As it turned out, if you started the php server with "php -S localhost:80" the server will be started with ipv6 support only!To access it via ipv4, you need to change the start up command like so: "php -S 127.0.0.1:80"which starts server in ipv4 mode only.
up
30
tamas at bartatamas dot hu
10 years ago
If your URI contains a dot, you'll lose the $_SERVER['PATH_INFO'] variable, when using the built-in webserver.I wanted to write an API, and use .json ending in the URI-s, but then the framework's routing mechanism broke, and it took a lot of time to discover that the reason behind it was its router relying on $_SERVER['PATH_INFO'].References:https://bugs.php.net/bug.php?id=61286
up
25
matthes at leuffen dot de
8 years ago
To output debugging information on the command line you can write output to php://stdout:<?php$path = $_SERVER["SCRIPT_FILENAME"];file_put_contents("php://stdout", "\nRequested: $path");echo "<p>Hello World</p>";?>
up
28
Ivan Ferrer
12 years ago
On Windows you may find useful to have a phpserver.bat file in shell:sendto with the folowing:explorer http://localhost:8888rem check if arg is file or dirif exist "%~1\" (  php -S localhost:8888 -t "%~1") else (  php -S localhost:8888 -t "%~dp1")then for fast web testing you only have to SendTo a file or folder to this bat and it will open your explorer and run the server.
up
8
deep at deepshah dot me
5 years ago
Listen on all addresses of IPv4:php -S 0.0.0.0:80Listen on all addresses of IPv6:php -S [::0]:80
up
1
sony at sony-ak dot com
5 years ago
To send environment variable as long as with PHP built-in web server, type like this.~$ MYENV=dev php -d variables_order=EGPCS -S 0.0.0.0:8000On PHP script we can check with this code.<?php  echo getenv('MYENV'); // print dev
up
-1
dachund at gmail dot com
7 years ago
I fiddled around with the internal webserver and had issues regarding handling static files, that do not contain a dot and a file extension.The webserver responded with 200 without any content for files with URIs like "/testfile".I am not certain if this is a bug, but I created a router.php that now does not use the "return false;" operation in order to pass thru the static file by the internal webserver.Instead I use fpassthru() to do that.In addition to that, my router.php can be configured to...- ... have certain index files, when requesting a directory- ... configure regex routes, so that, if the REQUEST_URI matches the regex, a certain file or directory is requested instead. (something you would do with nginx config or .htaccess ModRewrite)Maybe someone finds this helpful.================================<?php$indexFiles = ['index.html', 'index.php'];$routes = [  '^/api(/.*)?$' => '/index.php'];$requestedAbsoluteFile = dirname(__FILE__) . $_SERVER['REQUEST_URI'];// check if the the request matches one of the defined routesforeach ($routes as $regex => $fn){  if (preg_match('%'.$regex.'%', $_SERVER['REQUEST_URI']))  {    $requestedAbsoluteFile = dirname(__FILE__) . $fn;    break;  }}// if request is a directory call check if index files existif (is_dir($requestedAbsoluteFile)){  foreach ($indexFiles as $filename)  {    $fn = $requestedAbsoluteFile.'/'.$filename;    if (is_file($fn))    {      $requestedAbsoluteFile = $fn;      break;    }  }}// if requested file does not exist or is directory => 404if (!is_file($requestedAbsoluteFile)){  header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found');  printf('"%s" does not exist', $_SERVER['REQUEST_URI']);  return true;}// if requested file is'nt a php fileif (!preg_match('/\.php$/', $requestedAbsoluteFile)) {  header('Content-Type: '.mime_content_type($requestedAbsoluteFile));  $fh = fopen($requestedAbsoluteFile, 'r');  fpassthru($fh);  fclose($fh);  return true;}// if requested file is php, include itinclude_once $requestedAbsoluteFile;
up
-2
devoldemar
1 year ago
Built-in web server uses SAPI logging subsystem. Therefore all messages are written to standard error, and not to standard output stream.If you want to save server logs into a file, the following command will work:php -S 0.0.0.0:80 2>&1 | tee out.log
To Top