/** * Dump from a URL * * @param string path of the file to create (i.e. /home/foobar/index.html). * @param string url. */ static function fromURL($path, $url) { echo 'Saving "' . $url . '" into "' . $path . '"' . PHP_EOL; // Generate the view content $request = \photon\test\HTTP::baseRequest('GET', $url); $response = \photon\core\Dispatcher::match($request); // If the output is NOT HTML, write the content on disk $type = $response->headers['Content-Type']; if (strstr($type, 'text/html') === false) { file_put_contents($path, $response->content, LOCK_EX); return; } // If the output is HTML, generate extra data to write on disk echo 'Downloading extra content and patching links' . PHP_EOL; $dom = new \DOMDocument(); @$dom->loadHTML($response->content); // Lot of warning on HTML5 tags like nav $xpath = new \DOMXpath($dom); foreach ($xpath->query('//script[@src]') as $script) { $src = $script->getAttribute('src'); $script->setAttribute('src', static::downloadExtra($path, $src)); } foreach ($xpath->query('//a[@href]') as $a) { $href = $a->getAttribute('href'); if (substr($href, -1) === '/') { continue; } $a->setAttribute('href', static::downloadExtra($path, $href)); } foreach ($xpath->query('//link[@href]') as $link) { $href = $link->getAttribute('href'); $link->setAttribute('href', static::downloadExtra($path, $href)); } foreach ($xpath->query('//img[@src]') as $img) { $src = $img->getAttribute('src'); $img->setAttribute('src', static::downloadExtra($path, $src)); } $content = $dom->saveHTML(); file_put_contents($path, $content, LOCK_EX); }
/** * Process the request available on the socket. * * The socket is available for reading with recv(). */ public function processRequest($conn) { Timer::start('photon.process_request'); $uuid = request_uuid(); $mess = $conn->recv(); if ($mess->is_disconnect()) { // A client disconnect from mongrel2 before a answer was send // Use this event to cleanup your context (long polling socket, task queue, ...) $event_params = array('conn_id' => $mess->conn_id); Event::send('\\photon\\server\\Server\\processRequest::disconnect', null, $event_params); } else { // This could be converted to use server_id + listener // connection id, it will wrap but should provide enough // uniqueness to track the effect of a request in the app. $req = new \photon\http\Request($mess); $req->uuid = $uuid; $req->conn = $conn; list($req, $response) = \photon\core\Dispatcher::dispatch($req); // If the response is false, the view is simply not // sending an answer, most likely the work was pushed to // another backend. Yes, you do not need to reply after a // recv(). if (false !== $response) { if (is_string($response->content)) { $conn->reply($mess, $response->render()); } else { Log::debug(array('photon.process_request', $uuid, 'SendIterable')); $response->sendIterable($mess, $conn); } } } unset($mess); // Cleans the memory with the __destruct call. Log::perf(array('photon.process_request', $uuid, Timer::stop('photon.process_request'))); }
public function testViewFoundInSub() { $views = array(array('regex' => '#^/hello#', 'sub' => array(array('regex' => '#^/home/(.+)/$#', 'view' => function () { return false; }, 'name' => 'home'))), array('regex' => '#^/foo/(.+)/$#', 'view' => function () { throw new \Exception(); }, 'name' => 'foo_bar')); Conf::set('urls', $views); $headers = (object) array('METHOD' => 'GET'); $msg = new Message('dummy', 'dummy', '/hello/home/foo/', $headers, ''); $req = new \photon\http\Request($msg); list($req, $resp) = Dispatcher::dispatch($req); $this->assertEquals(false, $resp); }
public function testHPKP_enable() { Conf::set('middleware_security', array('hpkp' => true, 'hpkp_options' => array('pin-sha256' => array("MASTER_KEY_IN_BASE64", "BACKUP_KEY_IN_BASE64")))); $req = HTTP::baseRequest('GET', '/'); list($req, $resp) = Dispatcher::dispatch($req); $this->assertEquals(200, $resp->status_code); $this->assertArrayHasKey('Public-Key-Pins', $resp->headers); }