話說幾年前也寫過一篇筆記 [PHP] 使用 PHP built-in web server 及 PHP CodeIgniter framework 。現在則是使用的場景不同了,在筆記一下使用的情境。
不少嵌入式產品的 UI 是採用 Web 實作的,近幾年則是趨向於 App UI 。然而開發 embedded linux 產品時,其 Web UI 也是打包到 embedded linux 裡頭,這時要開發測時,就滿不方便。若只是單純改改裡頭 js code 則可以免強靠 Browser 做 JS Inject 來達成。
目前協助擴展嵌入式產品的 Web UI 維護團隊,過去曾嘗試把裡頭的 Web UI 使用 Vue.js 跟 webpack 打包機制,弄出個 webpack 自起 Web Server 並透過 devServer.proxy 把 CGI request 導向到實體 device ip。目前因為沒有啟用 Vue.js 所以也沒啟用 webpack 等機制,暫時就先用簡單的 PHP 內置Web Server 機制
$ php -S localhost:8000 -t PATH_DOCUMENT_ROOT
然而,在 fw build code 流程中,可能會有多處檔案搬移的設計,以 Web 來說,大概可以硬搞成 /js/main.js 其實擺在 /tmp/path1/js 中,而 /css/main.css 擺在 /tmp/path2/css 等等,這時就要靠 使用路由(Router)脚本 來處理
$ cat routing.php<?php$URL_PATH = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);if (!strncmp($URL_PATH, '/js/', 4)) {$file_path = '/tmp/path1/js' . $URL_PATH;if (file_exists($file_path)) {echo file_get_contents($file_path);return true;}}if (!strncmp($URL_PATH, '/css/', 4)) {$file_path = '/tmp/path2/css' . $URL_PATH;if (file_exists($file_path)) {echo file_get_contents($file_path);return true;}}return false;
使用:
$ php -S localhost:8000 -t /tmp routing.php
如此,若有一包 fw code 時,可透過 routing 機制指定某些檔案要從哪裡取得(例如需要 patch 的檔案等),因而避開 build code 後才能測試,便方便許多。另外,還須多補寫一下 /cgi-bin/ 的部分,在把 request 改發到對應的裝置上,如此在面對不需改動 CGI 問題時,可以輕鬆測試 Web UI。
另外,該 routing.php 也可以很結構化:
$ cat routing.php<?phpfunction log_info($message) {$stderr = fopen('php://stderr', 'w');fprintf($stderr, '=> '.$message."\n");fclose($stderr);}function tree_files( $input_file ) {if (!file_exists($input_file))return array();if (is_dir($input_file)) {$output = array();if ($handle = opendir($input_file)) {while (false !== ($file = readdir($handle))) {if ($file == '.' || $file == '..')continue;$path = $input_file . '/' . $file;if (!file_exists($path))continue;if (is_dir($path)) {$sub_output = tree_files( $path );foreach($sub_output as $f) {array_push($output, $f);}} else {array_push($output, $path);}}closedir($handle);}return $output;}return array( $input_file );}$request_handler = array('routing' => array('file' => array('/index.html' => '/tmp/study/haha.html','/world.html' => '/tmp/study/hello/',),'dir' => array('/js/' => '/tmp/study','/css/' => '/tmp/study',),),'content_type' => array('html' => 'text/html','htm' => 'text/html','css' => 'text/css','js' => 'text/javascript','svg' => 'image/svg+xml',),);$URL_PATH = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);$path_parts = pathinfo($URL_PATH);log_info('routing-init, URL_PATH:['.$URL_PATH.'], REQUEST_URI:['.$_SERVER['REQUEST_URI'].']');log_info('in routing-file mode');foreach($request_handler['routing']['file'] as $pattern => $target ) {if (!strncmp($URL_PATH, $pattern, strlen($pattern))) {log_info('in routing-file mode: match pattern: ['.$pattern.'], target: ['.$target.']');$path = is_dir($target) ? $target . $URL_PATH : $target;if (file_exists($path)) {$path_parts = pathinfo($URL_PATH);$content_type = isset($request_handler['content_type'][$path_parts['extension']]) ? $request_handler['content_type'][$path_parts['extension']]: mime_content_type($path);header('Content-Type: ' . $content_type);$size = filesize($path);header('Content-Length: '.$size);echo file_get_contents($path);log_info('routing-file, response: content-type:['.$content_type.'], content-length:['.$size.'], path:['.$path.']');return true;}}}log_info('in routing-dir mode');foreach($request_handler['routing']['dir'] as $pattern => $target ) {if (!strncmp($URL_PATH, $pattern, strlen($pattern))) {log_info('in routing-dir mode: match pattern: ['.$pattern.'], target: ['.$target.']');$path = $target.$URL_PATH;if (file_exists($path)) {$path_parts = pathinfo($URL_PATH);$content_type = isset($request_handler['content_type'][$path_parts['extension']]) ? $request_handler['content_type'][$path_parts['extension']]: mime_content_type($path);header('Content-Type: ' . $content_type);$size = filesize($path);header('Content-Length: '.$size);echo file_get_contents($path);log_info('routing-dir, response: content-type:['.$content_type.'], content-length:['.$size.'], path:['.$path.']');return true;}}}return false;
如此一來,在 /tmp/study 又建立一個檔案結構:
% tree /tmp/study/tmp/study├── css│ └── main.css├── haha.html├── hello│ └── world.html└── js└── main.js3 directories, 4 files
使用 php -S localhost:8000 routing.php 時,就會一些目錄切換的對應機制。
沒有留言:
張貼留言