forked from drush-ops/drush
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feature #1190984. Owen Barton, znerol. Lightweight built in http serv…
…er for development, using the httpserver library from adunar and the Envaya project.
- Loading branch information
Showing
8 changed files
with
350 additions
and
77 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
lib |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
<?php | ||
|
||
/** | ||
* @file | ||
* Classes extending the httpserver library that provide Drupal specific | ||
* behaviours. | ||
*/ | ||
|
||
/** | ||
* Extends the HTTPServer class, handling request routing and environment. | ||
*/ | ||
class DrupalServer extends HTTPServer { | ||
public $http_host; | ||
|
||
/** | ||
* This is the equivalent of .htaccess, passing requests to files if they | ||
* exist, and all other requests to index.php. We also set a number | ||
* of CGI environment variables here. | ||
*/ | ||
function route_request($request) { | ||
$cgi_env = array(); | ||
|
||
// Handle static files and php scripts accessed directly | ||
$uri = $request->uri; | ||
$doc_root = DRUPAL_ROOT; | ||
$path = $doc_root . $uri; | ||
if (is_file(realpath($path))) { | ||
if (preg_match('#\.php$#', $uri)) { | ||
// SCRIPT_NAME is equal to uri if it does exist on disk | ||
$cgi_env['SCRIPT_NAME'] = $uri; | ||
return $this->get_php_response($request, $path, $cgi_env); | ||
} | ||
return $this->get_static_response($request, $path); | ||
} | ||
|
||
// We pass in the effective base_url to our auto_prepend_script via the cgi | ||
// environment. This allows Drupal to generate working URLs to this http | ||
// server, whilst finding the correct multisite from the HTTP_HOST header. | ||
$cgi_env['RUNSERVER_BASE_URL'] = 'http://localhost:' . $this->port; | ||
|
||
// We pass in an array of $conf overrides using the same approach. | ||
// By default we set drupal_http_request_fails to FALSE, as the httpserver | ||
// is unable to process simultanious requests on some systems. | ||
// This is available as an option for developers to pass in their own | ||
// favorite $conf overrides (e.g. disabling css aggregation). | ||
$conf_inject = drush_get_option('conf-inject', array('drupal_http_request_fails' => FALSE)); | ||
$cgi_env['RUNSERVER_CONF'] = urlencode(serialize($conf_inject)); | ||
|
||
// Rewrite clean-urls | ||
$cgi_env['QUERY_STRING'] = 'q=' . ltrim($uri, '/'); | ||
if ($request->query_string != "") { | ||
$cgi_env['QUERY_STRING'] .= '&' . $request->query_string; | ||
} | ||
|
||
$cgi_env['SCRIPT_NAME'] = '/index.php'; | ||
$cgi_env['HTTP_HOST'] = $cgi_env['SERVER_NAME'] = $this->http_host; | ||
|
||
return $this->get_php_response($request, $doc_root . '/index.php', $cgi_env); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
<?php | ||
/** | ||
* @file | ||
* This file is included using the php "auto_prepend_file" option whenever | ||
* Drupal is used with runserver. | ||
* We use this to inject some specific changes so Drupal works correctly in | ||
* this environment. | ||
*/ | ||
|
||
// We set the base_url so that Drupal generates correct URLs for runserver | ||
// (e.g. http://localhost:8888/...), but can still select and serve a specific | ||
// site in a multisite configuration (e.g. http://mysite.com/...). | ||
$base_url = $_SERVER['RUNSERVER_BASE_URL']; | ||
|
||
/** | ||
* Configuration added here will apply to all sites. | ||
* This can be a useful place to apply generic development settings. | ||
* We hijack system_boot (which core system module does not implement) as | ||
* a convenient place to inject values into the $conf array. | ||
*/ | ||
if (!function_exists('system_boot')) { | ||
// Check function_exists as a safety net in case it is added in future. | ||
function system_boot() { | ||
global $conf; | ||
$conf_inject = unserialize(urldecode($_SERVER['RUNSERVER_CONF'])); | ||
// Merge in the injected conf, overriding existing items. | ||
$conf = array_merge($conf, $conf_inject); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
<?php | ||
|
||
/** | ||
* @file | ||
* Built in http server commands. | ||
* | ||
* This uses an excellent php http server library developed by Jesse Young | ||
* with support from the Envaya project. | ||
* See https://github.com/youngj/httpserver/ and http://envaya.org/. | ||
*/ | ||
|
||
/** | ||
* Supported version of httpserver. This is displayed in the manual install help. | ||
*/ | ||
define('DRUSH_HTTPSERVER_VERSION', '354b9142bf0cfd73063e28604d11288304531cd6'); | ||
|
||
/** | ||
* Directory name for httpserver. This is displayed in the manual install help. | ||
*/ | ||
define('DRUSH_HTTPSERVER_DIR_BASE', 'youngj-httpserver-'); | ||
|
||
/** | ||
* Base URL for automatic download of supported version of httpserver. | ||
*/ | ||
define('DRUSH_HTTPSERVER_BASE_URL', 'https://github.com/youngj/httpserver/tarball/'); | ||
|
||
/** | ||
* Implementation of hook_drush_help(). | ||
*/ | ||
function runserver_drush_help($section) { | ||
switch ($section) { | ||
case 'meta:runserver:title': | ||
return dt("Runserver commands"); | ||
case 'drush:runserver': | ||
return dt("Runs a lightweight built in http server for development. | ||
- Don't use this for production, it is neither scalable nor secure for this use. | ||
- If you run multiple servers simultaniously, you will need to assign each a unique port. | ||
- Use Ctrl-C or equivalent to stop the server when complete."); | ||
} | ||
} | ||
|
||
/** | ||
* Implementation of hook_drush_command(). | ||
*/ | ||
function runserver_drush_command() { | ||
$items = array(); | ||
|
||
$items['runserver'] = array( | ||
'description' => 'Runs a lightweight built in http server for development.', | ||
'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_SITE, | ||
'arguments' => array( | ||
'addr:port' => 'Host IP address and port number to bind to (default 127.0.0.1:8888). The IP is optional, in which case just pass in the numeric port.', | ||
), | ||
'options' => array( | ||
'php-cgi' => 'Name of the php-cgi binary. If it is not on your current $PATH you should include the full path. You can include command line parameters to pass into php-cgi.', | ||
'conf-inject' => 'Key-value array of variables to override in the $conf array for the running site. By default disables drupal_http_request_fails to avoid errors on Windows (which supports only one connection at a time). Note that as this is a key-value array, it can only be specified in a drushrc or alias file, and not on the command line.', | ||
), | ||
'aliases' => array('rs'), | ||
); | ||
return $items; | ||
} | ||
|
||
/** | ||
* Validate callback for runserver command. | ||
*/ | ||
function drush_core_runserver_validate() { | ||
if (version_compare(PHP_VERSION, '5.3.0') < 0) { | ||
return drush_set_error('RUNSERVER_PHP_VERSION', dt('The runserver command requires php 5.3, which could not be found.')); | ||
} | ||
if (!drush_shell_exec('which ' . drush_get_option('php-cgi', 'php-cgi'))) { | ||
return drush_set_error('RUNSERVER_PHP_CGI', dt('The runserver command requires the php-cgi binary, which could not be found.')); | ||
} | ||
} | ||
|
||
/** | ||
* Callback for runserver command. | ||
*/ | ||
function drush_core_runserver($addrport = '8888') { | ||
// Fetch httpserver to our /lib directory, if needed. | ||
$lib = drush_get_option('lib', DRUSH_BASE_PATH . '/lib'); | ||
$httpserverfile = $lib . '/' . DRUSH_HTTPSERVER_DIR_BASE . substr(DRUSH_HTTPSERVER_VERSION, 0, 7) . '/httpserver.php'; | ||
if (!drush_file_not_empty($httpserverfile)) { | ||
// Download and extract httpserver, and confirm success. | ||
drush_lib_fetch(DRUSH_HTTPSERVER_BASE_URL . DRUSH_HTTPSERVER_VERSION); | ||
if (!drush_file_not_empty($httpserverfile)) { | ||
// Something went wrong - the library is still not present. | ||
return drush_set_error('RUNSERVER_HTTPSERVER_LIB_NOT_FOUND', dt("The runserver command needs a copy of the httpserver library in order to function, and the attempt to download this file automatically failed. To continue you will need to download the package from !url, extract it into the !lib directory, such that httpserver.php exists at !httpserverfile.", array('!version' => DRUSH_HTTPSERVER_VERSION, '!url' => DRUSH_HTTPSERVER_BASE_URL . DRUSH_HTTPSERVER_VERSION, '!httpserverfile' => $httpserverfile, '!lib' => $lib))); | ||
} | ||
} | ||
|
||
// Include the library and our class that extends it. | ||
require_once $httpserverfile; | ||
require_once 'runserver-drupal.inc'; | ||
|
||
// Determine configuration. | ||
if (is_numeric($addrport)) { | ||
$addr = '127.0.0.1'; | ||
$port = $addrport; | ||
} | ||
else { | ||
$addrport = explode(':', $addrport); | ||
if (count($addrport) !== 2 && is_numeric($addrport[1])) { | ||
return drush_set_error('RUNSERVER_INVALID_ADDRPORT', dt('Invalid address/port argument - should be either numeric (port only), or in the "host:port" format..')); | ||
} | ||
$addr = $addrport[0]; | ||
$port = $addrport[1]; | ||
} | ||
|
||
// We delete any registered files here, since they are not caught by Ctrl-C. | ||
_drush_delete_registered_files(); | ||
|
||
// Create a new server instance and start it running. | ||
$server = new DrupalServer(array( | ||
'addr' => $addr, | ||
'port' => $port, | ||
'serverid' => 'Drush runserver', | ||
'php_cgi' => drush_get_option('php-cgi', 'php-cgi') . ' --define auto_prepend_file="' . DRUSH_BASE_PATH . '/commands/runserver/runserver-prepend.php"', | ||
)); | ||
$server->run_forever(); | ||
} |
Oops, something went wrong.