Completed
Push — master ( a7ea1b...3ac6d3 )
by Nazar
08:13
created

Controller::index_run_server()   B

Complexity

Conditions 6
Paths 2

Size

Total Lines 29
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 22
nc 2
nop 1
dl 0
loc 29
rs 8.439
c 0
b 0
f 0
1
<?php
2
/**
3
 * @package   Http server
4
 * @category  modules
5
 * @author    Nazar Mokrynskyi <[email protected]>
6
 * @copyright Copyright (c) 2015-2017, Nazar Mokrynskyi
7
 * @license   MIT License, see license.txt
8
 */
9
namespace cs\modules\Http_server\cli;
10
use
11
	React,
12
	cs\App,
13
	cs\ExitException,
14
	cs\Page,
15
	cs\User,
16
	cs\Response as System_response,
17
	cs\modules\Psr7\Request,
18
	cs\modules\Psr7\Response,
19
	Psr\Http\Message\ServerRequestInterface;
20
21
class Controller {
22
	public static function index_help () {
23
		return <<<HELP
24
<y>Http server module</y>
25
26
<y>Methods:</y>
27
  <g>run_server</g> Prints all cli paths and methods available for specified path
28
  <g>run_pool</g>   Displays help for module or path (should be provided by developer, otherwise will fallback to <g>cli</g>)
29
30
<y>Arguments:</y>
31
  <g>port</g>  Required for <g>run_server</g>, specifies port on which server will be running
32
  <g>ports</g> Required for <g>run_pool</g>, specifies ports on which server will be running (coma-separated list of ports or ports ranged separated by -)
33
34
<y>Examples:</y>
35
  Run HTTP server on port 8080:
36
    <g>./cli run_server:Http_server port=8080</g>
37
  Run pool of HTTP servers on ports 8080, 8081 and range of ports 8082-8087:
38
    <g>./cli run_pool:Http_server ports=8080,8081,8082-8087</g>
39
40
HELP;
41
	}
42
	/**
43
	 * @param \cs\Request $Request
44
	 *
45
	 * @throws ExitException
46
	 */
47
	public static function index_run_server ($Request) {
48
		$port = $Request->query('port');
49
		if (!$port) {
50
			throw new ExitException('Port is required', 400);
51
		}
52
		$_SERVER['SERVER_SOFTWARE'] = 'ReactPHP';
53
		$memory_cache_disabled      = false;
54
		$app                        = function (ServerRequestInterface $request) use (&$memory_cache_disabled) {
55
			try {
56
				System_response::instance()->init_with_typical_default_settings();
57
				Request::init_from_psr7($request);
58
				App::instance()->execute();
59
				if (!$memory_cache_disabled) {
60
					$memory_cache_disabled = true;
61
					User::instance()->disable_memory_cache();
62
				}
63
			} catch (ExitException $e) {
64
				if ($e->getCode() >= 400) {
65
					Page::instance()->error($e->getMessage() ?: null, $e->getJson());
66
				}
67
			}
68
			return Response::output_to_psr7(new React\Http\Response);
69
		};
70
71
		$loop   = React\EventLoop\Factory::create();
72
		$socket = new React\Socket\Server($port, $loop);
73
		$http   = new React\Http\StreamingServer([new React\Http\Middleware\RequestBodyBufferMiddleware(), $app]);
74
		$http->listen($socket);
75
		$loop->run();
76
	}
77
	/**
78
	 * @param \cs\Request $Request
79
	 *
80
	 * @throws ExitException
81
	 */
82
	public static function index_run_pool ($Request) {
83
		$ports = $Request->query('ports');
84
		if (!$ports) {
85
			throw new ExitException('Ports are required', 400);
86
		}
87
		$ports = static::prepare_ports($ports);
88
		foreach ($ports as $p) {
89
			static::cross_platform_server_in_background($p);
90
		}
91
		echo "Pool of Http servers started!\n";
92
	}
93
	/**
94
	 * @param string $ports
95
	 *
96
	 * @return int[]
97
	 */
98
	protected static function prepare_ports ($ports) {
99
		$result_ports = [];
100
		foreach (explode(',', $ports) as $p) {
101
			if (strpos($p, '-') !== false) {
102
				/** @noinspection SlowArrayOperationsInLoopInspection */
103
				$result_ports = array_merge($result_ports, range(...explode('-', $p)));
104
			} else {
105
				$result_ports[] = $p;
106
			}
107
		}
108
		sort($result_ports);
109
		return $result_ports;
110
	}
111
	/**
112
	 * Running Http server in background on any platform
113
	 *
114
	 * @param int $port
115
	 */
116
	protected static function cross_platform_server_in_background ($port) {
117
		$dir        = dirname(__DIR__);
118
		$supervisor = "php $dir/supervisor.php";
119
		$cmd        = escapeshellarg(PHP_BINARY.' '.DIR."/cli run_server:Http_server port=$port");
120
		if (strpos(PHP_OS, 'WIN') === false) {
121
			exec("$supervisor $cmd > /dev/null &");
122
		} else {
123
			pclose(popen("start /B $supervisor $cmd", 'r'));
124
		}
125
	}
126
}
127