(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

Использование преимуществ встроенного PHP сервера

Источник: habrahabr
WildZero

Одним из крутейший новшеств в php 5.4 является встроенный сервер, созданный специально для разработки и тестирования. Теперь вы можете писать и тестировать свой код не имея полноценного веб-сервера - просто запустите встроенный сервер, протестируйте свой код, и выключите его, когда закончите.
Сервер, так же, предоставляет возможность и для творческого использования. Например, вы можете распространять портативное web-приложение на CD или USB, или даже как десктопное приложение, созданное на PHP без использования GTK или других графических библиотек.

В мануале PHP подчеркивается, что встроенный сервер предназначен для разработки и рекомендуется не использовать его на боевом сервере. Отсутствуют какие-либо INI директивы отвечающие за сервер (за исключением раскрашивания вывода в консоли), и, кажется, что основная идея документации: "у нас теперь тоже есть Web сервер, отстаньте от нас".
Несмотря на это, я считаю, что встроенные сервер может быть ценным инструментом для разработки и тестирования. К примеру, на моей машине я использую предустановленный Apache с кастомной конфигурацией, подходящей для меня, но иногда я хочу попробовать какие-либо новые Web-приложения. Со встроенным web-сервером я могу протестировать приложение прямо из папки "downloads" или временной папки и переместить в обычную среду, только тогда, когда это будет необходимо.
Но для начала, это не так просто, ведь многие написанные приложения используют .htaccess и mod_rewrite. Но я уверен, что кто-то (может быть один из вас, почему бы и нет?) напишет адаптер для этого, и я хотел бы быть первым, кто протестируют его.
В этой статье я объясню некоторые основные примеры использования встроенного сервера и покажу вам как сделать его полезным для разработки и тестирования.

Используем встроенный сервер

Итак, для использования сервера нам необходим php 5.4 или выше. Для проверки версии PHP, выполните:

php -v

Так же вы можете определить доступен ли сервер в вашей сборке выполнив: 

php -h

и найдите там описание параметров "-S" и "-t", которые используются только для сервера.
Для проверки сервера вы можете создать в текущей директории файл index.php, который будет содержать в себе вызов функции phpinfo() и затем запустить сервер:

[ec2-user@ip-10-229-67-156 ~]$ php -S 127.0.0.1:8080
PHP 5.4.0RC7 Development Server started at Fri Feb 26 18:49:29 2012
Listening on 127.0.0.1:8080
Document root is /home/ec2-user
Press Ctrl-C to quit.

И теперь вы можете увидеть содержимое отданной встроенным web-сервером:
image
В консоль же будет писаться каждый запрос клиента:

[Sun Feb 26 18:55:30 2012] 80.180.55.37:36318 [200]: /
[Sun Feb 26 18:56:23 2012] 80.180.55.37:36584 [200]: /

Возвращаясь назад, разберем параметр командной строки "-S", который используется для указания адреса, с которого сервер будет доступен. Возможные значения:
localhost - сервер будет доступен только с локальной машины,
0.0.0.0 - на любому интерфейсе машины,
Любой внешний или серый IP - только на указанном IP
Параметр "-t" устанавливает указанную директорию "directory root". Например:

[ec2-user@ip-10-229-67-156 ~]$ php -S <localhost or your public IP>:8090 -t /home/ec2-user/public

Кроме того,. вы может указать имя конкретного файла-роутера. Например:

[ec2-user@ip-10-229-67-156 ~]$ php -S >localhost or your public IP>:8080 -t /home/ec2-user/public public/index.php

Вывод этого роутера будет парситься и выполняться сервером. Простой пример:

<?php
$extensions = array("php", "jpg", "jpeg", "gif", "css");

$path = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
$ext = pathinfo($path, PATHINFO_EXTENSION);
if (in_array($ext, $extensions)) {
    // let the server handle the request as-is
    return false;  


}

echo "<p>Welcome to PHP</p>";

Если скрипт вернет FALSE, тогда запрашиваемый URI будет обрабатываться сервером, который будет выдавать запрошенный ресурс, либо вернет 404 ошибку. Если скрипт возвращает что-либо ещё, вывод скрипта передастся клиенту. 
Хотя данный подход даёт нам больше контроля, есть несколько вещей, которые вы должны знать. Во-первых, PHP сервер отдаёт только минимальный набор HTTP заголовков:

Connection: closed
Content-Type: text/html
Host: aws-dev-01.vtardia.com
X-Powered-By: PHP/5.4.0RC7

D
Сравним это с заголовками, возвращаемыми сервером Apache:

Accept-Ranges: bytes
Connection: Keep-Alive
Content-Length: 631
Content-Type: text/html
Date: Sat, 04 Feb 2012 18:24:42 GMT
Etag: "bbb99-277-4ace8c5470a40"
Keep-Alive: timeout=15, max=100
Last-Modified: Wed, 14 Sep 2011 15:54:09 GMT
Server: Apache/2.2.21 (Unix) DAV/2

Если ваше приложение использует заголовки, то оно должно учитывать разницу в development-среде и в production.
Во-вторых, встроенный сервер имеет другое SAPI (Server API). Таким образом выполняя маршрутизацию в index,php вы можете определить на тестовом или боевом сервер происходит обращение к скрипту. php_sapi_name() вернет "cli-server" на встроенном сервере:

<?php
if (php_sapi_name() == "cli-server") {
    // running under built-in server so
    // route static assets and return false
    $extensions = array("php", "jpg", "jpeg", "gif", "css");
    $path = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
    $ext = pathinfo($path, PATHINFO_EXTENSION);
    if (in_array($ext, $extensions)) {
        return false;  
    }
}

Существует одна специальная INI директива - "cli_server.color". Данная директива возвращает раскрашенный вывод в консоли. Создайте пустой файл с именем cli-server.ini и вставьте эту строку:

cli_server.color = on

Вы можете создать уникальную конфигурацию окружения для вашего сервера, указав в вашем INI файле необходимые директивы. Не объявленные директивы примут значения по-умолчанию. Сейчас мы объявили только одну директиву - cli_server.color.
Запустить сервер с параметром "-c" с указанием INI файла:

[ec2-user@ip-10-229-67-156 ~]$ php -S localhost -c cli-server.ini

Если ваш терминал поддерживает цвета, то вы сможете увидеть "цветной" вывод в консоли. 200 статус будет выделен зеленым, 404 - оранжевым, а ошибки сценария будут выделены красным цветом.

Создаём персональный сервер

Теперь, когда вы знаете всё, что необходимо знать о встроенном сервере, давайте сделаем что-нибудь крутое. Создадим собственный портативный сервер!
Я начну со следующей структуры нашего приложения:

Папка "library" содержит код приложения, "public" - корневая директория, содержит index.php и несколько статичных файлов. Особое внимание в этом руководстве будет уделено папке "server", и поэтому наше приложение будет состоять из простого "Hello Word!" и нескольких картинок и css.
Наша цель - получить возможность запускать сервер из директории приложения одной командой, а наш сервер будет заботиться о роутинге, HTTP заголовках и ошибках.

[ec2-user@ip-10-229-67-156 myapp]$  ./start.sh

Давайте рассмотрим сценарий запуска:

#! /bin/bash

INIFILE="$(pwd)/server/server.ini"
DOCROOT="$(pwd)/public"
ROUTER="$(pwd)/server/router.php"
HOST=0.0.0.0
PORT=8080

PHP=$(which php)
if [ $? != 0 ] ; then
    echo "Unable to find PHP"
    exit 1
fi

$PHP -S $HOST:$PORT -c $INIFILE -t $DOCROOT $ROUTER

Я предполагаю, что скрипт запускается из директории приложения, поэтому INIFILE, DOCROOT, ROUTER определяются используя pwd. Путь до php определяется используя команду which. Если php не был найден в пользовательском $PATH, то скрипт завершит работу ошибкой.
Данный способ работает достаточно хорошо, но давайте предоставим пользователю возможность изменить любой из заданных параметров из командной строки, например:

if [ ! -z $INIFILE ]; then
    INIFILE="$(pwd)/server/server.ini"
fi

Продолжим, папка "errors" содержит файлы для сообщений об HTTP ошибках. Вот пример о 403 ошибке: хотя я и использовал только HTML, скрипт будет подключен, использую include, поэтому вы можете использовать любой php код:

<!doctype html>  
<html lang="en">
 <head>
  <meta charset="utf-8">
  <title>403</title>  
 </head>
 <body>
  <h1>403: Forbidden</h1>
  <p>Sorry, the requested resource is not accessible.</p>
 </body>  
</html>

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

<?php
// Set timezone
date_default_timezone_set("UTC");

// Directory that contains error pages
define("ERRORS", dirname(__FILE__) . "/errors");

// Default index file
define("DIRECTORY_INDEX", "index.php");

// Optional array of authorized client IPs for a bit of security
$config["hostsAllowed"] = array();

function logAccess($status = 200) {
    file_put_contents("php://stdout", sprintf("[%s] %s:%s [%s]: %s\n",
        date("D M j H:i:s Y"), $_SERVER["REMOTE_ADDR"],
        $_SERVER["REMOTE_PORT"], $status, $_SERVER["REQUEST_URI"]));
}

// Parse allowed host list
if (!empty($config['hostsAllowed'])) {
    if (!in_array($_SERVER['REMOTE_ADDR'], $config['hostsAllowed'])) {
        logAccess(403);
        http_response_code(403);
        include ERRORS . '/403.php';
        exit;
    }
}

// if requesting a directory then serve the default index
$path = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
$ext = pathinfo($path, PATHINFO_EXTENSION);
if (empty($ext)) {
    $path = rtrim($path, "/") . "/" . DIRECTORY_INDEX;
}

// If the file exists then return false and let the server handle it
if (file_exists($_SERVER["DOCUMENT_ROOT"] . $path)) {
    return false;
}

// default behavior
logAccess(404);
http_response_code(404);
include ERRORS . "/404.php";

В первых строках я определяю некоторые глобальные параметры, такие как DIRECTORY_INDEX, директория с шаблонами ошибок. Параметр date_default_timezone_set() должен совпадать с настройками ОС, иначе будут несоответствия между записями в логе и на сервере. Так же я добавил список разрешенных IP адресов, для повышения безопасности.
Функция logAccess() необходима, потому что когда скрипт роутинга принимает запрос лог сервера по-умолчанию игнорируется. Функция принимает только код статуса, а формат вывода полностью соответствует формату сервера. 
Наша первая задача - проверка безопасности. Если IP клиента не находится в массиве разрешенных IP, выводим сообщение об ошибке и завершаем работу скрипта. Нам необходимо отдавать код статуса отличный от 200 и функция header() не будет работать в здесь, поэтому мы используем новую функцию - http_response_code.
Если IP клиента находится в массиве разрешенных IP, то следующий наш шаг - получение запрашиваемого пути и расширения файла. Если расширение пустое, считаем, что пользователь запрашивает папку и строим получаем путь, используя определенный сначала DIRECTORY_INDEX. 
В завершении, если запрашиваемый файл существует, возвращаем FALSE, и позволяем серверу обратиться к файлу. Если же нет, то отображается сообщение о 404 ошибке. 

Резюме

Это всё. Как видите, php сервер просто в использовании. Наш персональный сервер очень прост. Код можно оптимизировать и включать в более сложные и функциональные классы. Happy coding!

Ссылки по теме


 Распечатать »
 Правила публикации »
  Написать редактору 
 Рекомендовать » Дата публикации: 02.11.2012 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
Quest Software. Toad for SQL Server Development Suite
Inventory 9
Panda Mobile Security - ESD версия - на 1 устройство - (лицензия на 1 год)
The BAT! Home Upgrade- 1 компьютер
DevExpress / ASP.NET Subscription
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Безопасность компьютерных сетей и защита информации
Новости ITShop.ru - ПО, книги, документация, курсы обучения
СУБД Oracle "с нуля"
OS Linux для начинающих. Новости + статьи + обзоры + ссылки
Мастерская программиста
ЕRP-Форум. Творческие дискуссии о системах автоматизации
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
 



    
rambler's top100 Rambler's Top100