/** * Handle the request * * @param Aspamia_Http_Request $request * @return Aspamia_Http_Response */ public function handle(Aspamia_Http_Request $request) { if ($this->_config['document_root']) { $document_root = $this->_config['document_root']; } else { $document_root = getcwd(); } $file = rtrim($document_root, '/') . '/' . trim($request->getUri(), '/'); if (!file_exists($file)) { // not found - 404 return self::_errorResponse(404, "The requested URL does not exist"); } if (!is_readable($file)) { // not readable - 403 return self::_errorResponse(403, "You have no permissions to read the requested URL"); } if (!$this->_config['follow_symlinks'] && is_link($file)) { // symlink and we can't follow - 404 return self::_errorResponse(404, "The requested URL does not exist"); } if (is_dir($file)) { // Directory - look for index file foreach ($this->_config['directory_index'] as $index) { $index = $file . '/' . $index; if (file_exists($index) && is_file($index)) { return $this->_serveFile($index); } } // No index found - can we do directory listing? if ($this->_config['list_directories']) { return $this->_serveDirListing($file); } else { // Directory and can't list return self::_errorResponse(403, "Directory listing not allowed"); } } if (is_file($file)) { return $this->_serveFile($file); } else { // So what the hell it is? require_once 'Aspamia/Http/Server/Handler/Exception.php'; throw new Aspamia_Http_Server_Handler_Exception("No idea how to serve '{$file}'"); } }
/** * Handle the request * * @param Aspamia_Http_Request $request * @return Aspamia_Http_Response */ public function handle(Aspamia_Http_Request $request) { if (!$this->_config['handler']) { require_once 'Aspamia/Http/Server/Handler/Exception.php'; throw new Aspamia_Http_Server_Handler_Exception("No CGI handler was set"); } if (isset($this->_config['document_root'])) { $document_root = $this->_config['document_root']; } else { $document_root = getcwd(); } // Parse the URI $urlInfo = parse_url($request->getUri()); // Build the translated path $script_path = rtrim($document_root, '/') . (isset($this->_config['handler_script']) ? '/' . ltrim($this->_config['handler_script']) : $urlInfo['path']); // Set up the environment $environment = array('SERVER_SOFTWARE ' => 'Aspamia/' . Aspamia_Http_Server::ASPAMIA_VERSION, 'SERVER_NAME' => $request->getLocalAddress(), 'SERVER_PROTOCOL' => 'HTTP/' . $request->getHttpVersion(), 'SERVER_PORT' => $this->_server->getConfig('bind_port'), 'DOCUMENT_ROOT' => $document_root, 'GATEWAY_INTERFACE' => 'CGI/1.1', 'REQUEST_METHOD' => $request->getMethod(), 'REQUEST_URI' => $request->getUri(), 'PATH_INFO' => $request->getUri(), 'PATH_TRANSLATED' => $script_path, 'SCRIPT_NAME' => $urlInfo['path'], 'REMOTE_ADDR' => $request->getRemoteAddress(), 'CONTENT_TYPE' => $request->getHeader('content-type'), 'CONTENT_LENGTH' => $request->getHeader('content-length'), 'PATH' => getenv('PATH')); if (isset($urlInfo['query'])) { $environment['QUERY_STRING'] = $urlInfo['query']; } // Add the HTTP headers to the environment $headers = $request->getAllHeaders(); unset($headers['content-type'], $headers['content-length']); foreach ($headers as $header => $value) { $key = 'HTTP_' . strtoupper(strtr($header, '-', '_')); $environment[$key] = $value; } // Open the CGI handler process $cgi_proc = proc_open($this->_config['handler'], array(array('pipe', 'r'), array('pipe', 'w'), array('file', '/tmp/cgi-error.log', 'a')), $pipes, null, $environment); if (!$cgi_proc) { require_once 'Aspamia/Http/Server/Handler/Exception.php'; throw new Aspamia_Http_Server_Handler_Exception("Unable to run CGI handler"); } // Write body, if any, to the CGI STDIN fwrite($pipes[0], $request->getBody()); fclose($pipes[0]); // Read the response headers $headerlines = Aspamia_Http_Message::readHeaders($pipes[1]); if (empty($headerlines)) { $headers = array('content-type' => 'text/plain', 'x-aspamia-message' => 'missing-cgi-headers'); $code = 200; $message = 'Ok'; $httpVersion = $request->getHttpVersion(); $response = new Aspamia_Http_Response($code, $headerlines, '', $httpVersion, $message); } else { if (strpos($headerlines[0], 'HTTP/') === 0) { // Got a status line, use it $statusLine = explode(' ', array_shift($headerlines), 3); if (!count($statusLine) == 3) { require_once 'Aspamia/Http/Server/Handler/Exception.php'; throw new Aspamia_Http_Server_Handler_Exception("Unable to read status line from CGI handler"); } $code = (int) $statusLine[1]; $message = $statusLine[2]; $httpVersion = substr($statusLine[0], 5); $response = new Aspamia_Http_Response($code, $headerlines, '', $httpVersion, $message); } else { $response = new Aspamia_Http_Response(200, $headerlines, '', $request->getHttpVersion()); if ($status = $response->getHeader('status')) { $status = explode(' ', $status); if (isset($status[0])) { $response->setStatus((int) $status[0]); } if (isset($status[1])) { $response->setMessage($status[1]); } $response->setHeader('status', false); } } } // Read the response body $body = stream_get_contents($pipes[1]); fclose($pipes[1]); // Close CGI process proc_close($cgi_proc); // Create the status line $response->setBody($body); $response->setHeader('content-length', strlen($body)); return $response; }
protected function _readRequest($connection) { return Aspamia_Http_Request::read($connection); }
/** * Test that trying to set invalid header names throw an exception * * @param string $header * * @dataProvider invalidHeaderProvider * @expectedException Aspamia_Http_Exception */ public function testInvalidHeaderName($header) { $request = new Aspamia_Http_Request('GET', '/'); $request->setHeader($header); }
/** * Try to match the request to a route * * @param string $route * @param Aspamia_Http_Request $request * @return boolean */ protected function _routeMatch($route, $request) { return (bool) preg_match("#^{$route}#", $request->getUri()); }
/** * Read an HTTP request from an open socket and return it as an object * * Will not read the full body unless explicitly asked to. * * @param resource $connection * @param boolean $read_body * @return Aspamia_Http_Request */ public static function read($connection, $read_body = false) { // Get the local and remote address of the connection $localAddress = stream_socket_get_name($connection, false); $remoteAddress = stream_socket_get_name($connection, true); $headerlines = self::readHeaders($connection); if (empty($headerlines)) { require_once 'Aspamia/Http/Exception.php'; throw new Aspamia_Http_Exception("Unable to read request: headers are empty"); } $requestline = explode(' ', array_shift($headerlines), 3); if (!count($requestline) == 3) { require_once 'Aspamia/Http/Exception.php'; throw new Aspamia_Http_Exception("Unable to read request: invalid HTTP request line '{$headerlines[0]}'"); } $protocol = explode('/', $requestline[2]); if (!($protocol[0] == 'HTTP' && ($protocol[1] == '1.1' || $protocol[1] == '1.0'))) { require_once 'Aspamia/Http/Exception.php'; throw new Aspamia_Http_Exception("Unsupported protocol version: {$requestline[2]}"); } $method = strtoupper($requestline[0]); $uri = $requestline[1]; $headers = array(); foreach ($headerlines as $line) { $header = explode(":", $line, 2); if (!count($header) == 2) { require_once 'Aspamia/Http/Exception.php'; throw new Aspamia_Http_Exception("Invalid HTTP header format: {$line}"); } $headers[strtolower(trim($header[0]))] = trim($header[1]); } $request = new Aspamia_Http_Request($method, $uri, $headers); $request->_httpVersion = $protocol[1]; $request->_socket = $connection; $request->_localAddress = $localAddress; $request->_remoteAddress = $remoteAddress; if ($read_body) { $request->_readBody(); } return $request; }
/** * Called after the request is recieved. The request object is passed in * * @param Aspamia_Http_Request $request */ public function postRequest(Aspamia_Http_Request $request) { $this->_log->info("Request: {$request->getMethod()} {$request->getUri()}"); }