今天,试了一下通过 php5.4.45 内置的webserver , 在Windows XP 上面能够跑起公司的一个项目,完全无压力。哈哈,只要一个php 就可以,不需要 Apache , Nginx(full-featured web server )这些功能完善的webserver.

http://www.sitepoint.com/taking-advantage-of-phps-built-in-server/

One of the cooler features of the new PHP 5.4 release is a built-in web server designed specifically for development and testing. Now you can write and test your code without having to have a full-fledged LAMP configuration – just launch a the built-in server from the command line, test your code, and then shut it down when you’re finished.

The server lends itself to other creative uses, too. For example, you could distribute portable web applications on CD ROMs or USB sticks, or even as desktop applications, all created with PHP without needing GTK or other graphic libraries.

Some may point out that PHP is a language originally designed to be used on the web in the first place, while other languages like Python and Ruby are not, so it makes more sense for the others to provide a basic server environment to help kick-start web development. They’ll argue PHP doesn’t need a built-in server. Besides, most systems today come with a personal web server already installed or installable with a few commands or clicks.

Indeed the PHP manual stresses that the new built-in server is intended for development use only and recommends against using it in production. There are no special INI directives for it except for one (which colorizes logging output sent to the console), and the general tone of the documentation seems to be “we too have a web server now, stop bothering us.”

Despite this, the server made it in version 5.4, and it’s my opinion it can be a valuable tool for both developing and testing. On my machine for example I use OSX’s pre-installed Apache with a custom configuration that suits my development style, but sometimes I want to try a some new webapp. With PHP’s built-in server, I could test the application right from my download or temp directories and then move it to my regular environment only if I really need to.

Well, it’s not so simple at first because a lot of apps are written with Apache in mind and make use of.htaccess files and mod_rewrite. But I’m quite sure that someone out there (maybe one of you, why not?) will write and adapter for this features and I’d like to be the first to test it.

In this article I’ll explain some basic uses of the new built-in server and show you how to build a portable personal development server useful for quickly testing your applications. I’m sure you’re just as anxious as I am to get started, so let’s do it!

Using the Built-in Server

You’ll need to have PHP 5.4 or greater installed to use the built-in server. To verify your version of PHP, invoke php -v in a terminal. You can then determine if the server is available in your build by running php -h and looking for the -S and -t options which are specific to the server.

You can test the server by creating a basic index.php file in the your current directory which contains a call to phpinfo(), and then launching the server like so:

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

In your browser you should now be able to see the content served by the built-in server.

A new log line will be written to the console window for each client access:

[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]: /

Looking back at the PHP’s command line options, -S is used to specify the address which the server will bind to. Its value can be:

  • localhost – the server is accessible only at the local machine
  • 0.0.0.0 – the server is accessible from any interface of your machine, wired or wireless
  • any of your public or private IP addresses – the server is accessible only at the specific address

-t allows you to tell the server to target another directory for its document root. For example:

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

Alternatively, you can also provide the name of a specific PHP file, such as an index.php or a customrouter.php file.

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

The output of such a router script will be parsed and executed by the server. Here is a basic example:

<?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>";

If the script returns false then the requested URI will be processed by the server, which outputs the requested resource either as-is or as a 404 error. If the script returns something else, then the output is passed to the client.

While such an approach gives us more control, there are a couple of things you should be aware of. First, the PHP server returns only a minimal set of HTTP headers:

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

Compare this to the set of typical HTTP headers returned by 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

If your application makes use of server headers, these must be consistent in both the development/test environment (the built-in server) and the production environment (Apache/IIS/Nginx).

Second, the PHP server has a different SAPI (Server API), so you perform the routing conditionally whetherindex.php is served from the built-in server or a production server. php_sapi_name() will return “cli-server” when you’re using the built-in 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;
}
}

There is one special INI directive for the built-in server; the cli_server.color directive turns on colorized log output in the console output. Create an empty text file called cli-server.ini and insert this line:

cli_server.color = on

You can create a unique configuration environment for your server inside your new custom INI file, and any non specified directives will assume the default value. Here we’ve just specified the cli_server.color directive.

Kill the previously running process, and start it again but this time use -c to specify the new file.

[ec2-user@ip-10-229-67-156 ~]$ php -S <localhost or your public IP>:8080 -c cli-server.ini

If your terminal supports color you should see colored output lines now. 200 statuses are shown in green, orange is used for 404 statuses, and you’ll see red for errors inside the requested script.

Building a Custom Server

Now that you know all there is to know about the built-in web server in PHP, let’s use that knowledge to do something cool. Let’s program a custom portable server!

I’ll start with the following sample directory structure for the application:

The library directory contains the application’s code, the public directory will be our document root and will contain the index.php and some sample static files. The focus of this tutorial will be the serverdirectory, so the application will consist on a simple HelloWorld script and some static content (an image and a CSS file).

The goal is to be able to start the server from within the application directory with one command and our server will take care of routing, headers, and HTTP errors.

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

Let’s start to examine the start script, which is a simple shell script:
[shell]#! /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[/shell]
The lines just after the #! shebang are definable settings. I’m assuming the script is started from the application directory, so the INIFILEDOCROOT and ROUTER paths are all calculated from there usingpwd. Then the path to PHP is identified using the output of the which command. If PHP is not found in the user’s $PATH by which, the command returns a non-zero value and the script will exit with an error.

The approach here works well enough, but you may have to be more robust depending on your needs. An alternate approach would be to provide the user an option to override any of the defined settings from the command line, for example:
[shell]if [ ! -z $INIFILE ]; then
    INIFILE="$(pwd)/server/server.ini"
fi[/shell]
Continuing on, the errors directory contains files for HTTP error messages. Here’s an example of the 403 message; though I’ve used only HTML, the script will be included using include in the router so you can add any PHP you’d like.

<!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>

And then there’s the router.php file that does all the work. The goal of this file is to grab and manage all the requests and pass them to the server only if they are existing files. All the error pages are managed internally by including the templates.

<?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]: %sn",
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";

In the first lines I define some global settings such as the directory index file and the error templates directory. The parameter of date_default_timezone_set() must match with that of your system or you will have an inconsistency between the log entries of the script and that of the server. I’ve also added an optional list of allowed client IPs to improve the security.

The logAccess() function is needed because when the router script takes care of the request the server default log is bypassed. This function takes only the status code parameter and formats the output to match exactly that of the server.

Our first parsing task is the security check: if a list of hosts is defined above and the client is not in this list we serve an error message and close the script. We need to output a status code different than 200 in case of error and the header() function will not work in this context, so the right function to use is the newhttp_response_code().

If the client is allowed to go further, the next thing we do is to extract the requested path and its extension. In case the extension is empty the user is requesting a directory so we build the complete path using the default directory index file.

Finally if the requested path corresponds to an existing file the script returns false and let the server handle it. If not, the default behavior is performed, displaying a 404 error page.

Summary

And that’s it. As you can see, the PHP server is simple and rather straightforward to use. Our custom quick server is very basic, the code could be optimized and encapsulated into a more complex and full-featured class. As usual you can download the source code from GitHub to play with. Happy coding!

php 内置的 webserver 研究。的更多相关文章

  1. Python内置类属性,元类研究

    Python内置类属性 我觉得一切都是对象,对象和元类对象,类对象其实都是一样的,我在最后进行了证明,但是只能证明一半,最后由于元类的父类是type,他可以阻挡对object属性的访问,告终 __di ...

  2. Nginx-解读内置非默认模块 ngx_http_stub_status_module

    1.Background ngx_http_stub_status_module 是一个 Nginx 的内置 HTTP 模块,该模块可以提供 Nginx 的状态信息.默认情况下这个模块是不被编译进来的 ...

  3. 【原创】Matlab.NET混合编程技巧之直接调用Matlab内置函数

                  本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新    Matlab和C#混合编程文章目录 :[目录]Matlab和C#混合编程文章目录 在我的上一篇文章[ ...

  4. vs2013 内置IIS Express相关问题

    问题描述,以前做的程序迁移到vs2013后出现500.22问题. HTTP 错误 500.22 - Internal Server Error 检测到在集成的托管管道模式下不适用的 ASP.NET 设 ...

  5. javascript内置属性——arguments

    arguments是javascript中的内置属性,可以直接调用函数的参数,作用类似Array,但本身并不是数组.这次发现它是为了实现封装函数,将不确定数量的数字乘积.比如function mult ...

  6. makefile 分析 -- 内置变量及自动变量

    makefile 分析1  -p 选项,可以打印出make过程中的数据库, 下面研究一下内置的变量和规则. -n 选项, 只运行,不执行, -d 选项,相当于--debug=a,  b(basic), ...

  7. 【微网站开发】之微信内置浏览器API使用

    最近在写微网站,发现了微信内置浏览器的很多不称心的地方: 1.安卓版的微信内浏览器底部总是出现一个刷新.前进.后退的底部栏,宽度很大,导致屏幕显示尺寸被压缩 2.分享当前网站至朋友圈时,分享的图片一般 ...

  8. [Sciter系列] MFC下的Sciter–4.HTML与图片资源内置

    [Sciter系列] MFC下的Sciter–4.HTML与图片资源内置,防止代码泄露. 本系列文章的目的就是一步步构建出一个功能可用,接口基本完善的基于MFC框架的SciterFrame程序,以此作 ...

  9. Windows Azure 自动伸缩已内置

     WindowsAzure平台提供的主要优点之一是能够在有需要时快速缩放云中的应用程序以响应波动.去年7月以前,您必须编写自定义脚本或使用其他工具(如Wasabi或MetricsHub)来启用自动 ...

随机推荐

  1. 昨天上架出现问题,you binary is not optimized for iphone5.。。。。

    这个时候只需要加一个lanuch image 就可以了

  2. css float 布局

    .clearfix:after { content: ''; display: table; clear: both; } .clearfix {; }

  3. JS-将input输入框写入的小写字母全部转换成为大写字母的JS代码

    <input name="htmer" type="text" onkeyup="this.value=this.value.toUpperCa ...

  4. WampServer 下载以及安装问题

    WampServer 3.0 下载: http://dl.pconline.com.cn/download/52877-1.html 碰到的问题DDL无法添加,解决方法: http://jingyan ...

  5. MySQL操作失误导致mysql数据库查看不了

    使用  show databases; +--------------------+| Database           |+--------------------+| information_ ...

  6. Swift & OC 混编 浅析

    转载自:http://www.infoq.com/cn/articles/wangyi-cartoon-swift-mixed-practice?utm_campaign=rightbar_v2&am ...

  7. 如何给grldr.mbr和grldr改名

    grldr修改方法: 比如要把grldr 改成gzldr :1.先把文件名改成gzldr:2.用ultraedit或winhex打开gzldr:3.虽然文本框全都是乱码,别管它,把光标定位在右边文本框 ...

  8. python 函数部分

    #初始化 def init(data): data['first']={} data['middle']={} data['last']={} #查看条件 def lookup(data,label, ...

  9. 简单日历,纯js

    <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...

  10. Xshell无法连接虚拟机中的Ubuntu

    遇到问题: VAWare中安装了Ubuntu-Desktop,Xshell连接失败 解决办法: 首先确认虚拟Ubuntu可以正常联网 可能原因是没有安装openssh服务 sudo apt-get i ...