Skip to content

Instantly share code, notes, and snippets.

@chobie
Created September 17, 2010 19:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chobie/584743 to your computer and use it in GitHub Desktop.
Save chobie/584743 to your computer and use it in GitHub Desktop.
<?php
declare(encoding='utf8');
namespace Tsunami;
$app = new Application(array(
"/"=>function($request){
echo "Hello World";
}
)
);
$server = new HttpServer($app);
$server->listen("0.0.0.0","8888");
/**
* Libevent Http Server for Sample Application
*
* @author chobi_e
*
* system required.
* php 5.3 higher.
* pecl http
* svn co http://svn.php.net/repository/pecl/http/trunk pecl_http
* pecl libevent
* svn co http://svn.php.net/repository/pecl/libevent/trunk pecl_libevent
*
*/
class Application{
public $cached;
protected $application;
public function __construct(Array $application){
$this->cached = array();
$this->application = $application;
}
public function __invoke($request){
$response = array();
$path = $request->normaraizedURI();
if(isset($this->cached[$path])){
$this->cached[$path]($request);
return;
}
foreach($this->application as $location => $invoke){
if($location == $request->normaraizedURI()){
$this->cached[$location] = $invoke;
$invoke($request);
return;
}
}
}
}
class HttpServer{
protected $address;
protected $port;
protected $socket;
protected $application;
protected $number = 0;
protected $connections = array();
protected $buffers = array();
protected $result = array();
private function bind($address,$port){
$socket = stream_socket_server("tcp://" . $address . ":" . $port, $errno, $errstr);
if(is_resource($socket)){
stream_set_blocking($socket,0);
$this->socket = $socket;
return true;
}
return false;
}
public function error($buffer,$error,$id){
event_buffer_disable($this->buffers[$id], EV_READ | EV_WRITE);
event_buffer_free($this->buffers[$id]);
fclose($this->connections[$id]);
unset($this->buffers[$id], $this->connections[$id],$this->result[$id]);
}
public function write($buffer,$id){
event_buffer_disable($this->buffers[$id], EV_READ | EV_WRITE);
event_buffer_free($this->buffers[$id]);
fclose($this->connections[$id]);
unset($this->buffers[$id], $this->connections[$id],$this->result[$id]);
}
public function read($buffer,$id){
while ($read = event_buffer_read($buffer, 8192)) {
$this->result[$id] .= $read;
}
if(!preg_match("/\r?\n\r?\n/m",$this->result[$id])){
return;
}
try{
$message = new \HttpMessage(ltrim($this->result[$id]));
}catch(Exception $e){
ev_error($buffer,$id);
}
$_SERVER = $message->getHeaders();
$_SERVER["REQUEST_URI"] = $message->getRequestUrl();
//ob_start();
$request = new Request($_SERVER['REQUEST_URI']);
$method = $this->application;
ob_start();
$method($request);
$data = ob_get_clean();
$response = array();
$response[] = "HTTP/1.0 200 OK";
$response[] = "Content-type: text/html; charset='utf8'";
$response[] = "";
$response[] = $data;
event_buffer_write ($buffer,join("\r\n",$response));
}
public function accept($socket, $event, $base){
if(is_resource($socket)){
$this->number++;
$accept = @stream_socket_accept($socket);
$this->result[$this->number] = "";
if(is_resource($accept)){
stream_set_blocking($accept,0);
$buffer = event_buffer_new($accept,array($this,"read"),array($this,"write"),array($this,"error"),$this->number);
event_buffer_base_set($buffer, $base);
event_buffer_timeout_set($buffer, 30, 30);
event_buffer_watermark_set($buffer, EV_READ, 0, 0xffffff);
event_buffer_priority_set($buffer, 10);
event_buffer_enable($buffer, EV_READ | EV_PERSIST);
$this->connections[$this->number] = $accept;
$this->buffers[$this->number] = $buffer;
}else{
// something wrong.
}
}
}
public function __construct($application){
$this->application = $application;
}
public function listen($address,$port){
$this->bind($address,$port);
$base = event_base_new();
$event = event_new();
event_set($event, $this->socket, EV_READ | EV_PERSIST, array($this,"accept"),$base);
event_base_set($event, $base);
event_add($event);
event_base_loop($base);
}
}
class Request{
protected $uri;
public function normaraizedURI(){
return $this->uri;
}
public function __construct($path){
$this->uri = $path;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment