/**
  * Handle a single request
  *
  * @param   string method request method
  * @param   string query query string
  * @param   [:string] headers request headers
  * @param   string data post data
  * @param   peer.Socket socket
  * @return  int
  */
 public function handleRequest($method, $query, array $headers, $data, Socket $socket)
 {
     $url = parse_url($query);
     $f = new File($this->docroot, strtr(preg_replace('#\\.\\./?#', '/', urldecode($url['path'])), '/', DIRECTORY_SEPARATOR));
     if (!is_file($f->getURI())) {
         return call_user_func($this->notFound, $socket, $url['path']);
     }
     // Implement If-Modified-Since/304 Not modified
     $lastModified = $f->lastModified();
     if ($mod = $this->header($headers, 'If-Modified-Since')) {
         $d = strtotime($mod);
         if ($lastModified <= $d) {
             return $this->sendHeader($socket, 304, 'Not modified', array());
         }
     }
     try {
         $f->open(FILE_MODE_READ);
     } catch (IOException $e) {
         $this->sendErrorMessage($socket, 500, 'Internal server error', $e->getMessage());
         $f->close();
         return;
     }
     // Send OK header and data in 8192 byte chunks
     $sc = $this->sendHeader($socket, 200, 'OK', array('Last-Modified' => gmdate('D, d M Y H:i:s T', $lastModified), 'Content-Type' => MimeType::getByFileName($f->getFilename()), 'Content-Length' => $f->size()));
     while (!$f->eof()) {
         $socket->write($f->read(8192));
     }
     $f->close();
     return $sc;
 }
 /**
  * Factory method
  *
  * @param  var arg either an InputStream, File, or IOElement
  * @return self
  * @throws lang.IllegalArgumentException
  */
 public static function of($arg)
 {
     if ($arg instanceof \io\streams\InputStream) {
         return new self($arg);
     } else {
         if ($arg instanceof \io\File) {
             return (new self($arg->in()))->withMediaType(MimeType::getByFileName($arg->getFileName()))->withContentLength($arg->getSize())->withLastModified(new Date($arg->lastModified()));
         } else {
             if ($arg instanceof \io\collections\IOElement) {
                 return (new self($arg->getInputStream()))->withMediaType(MimeType::getByFileName($arg->getURI()))->withContentLength($arg->getSize())->withLastModified($arg->lastModified());
             } else {
                 throw new \lang\IllegalArgumentException('Expected either an InputStream, File, or IOElement, have ' . \xp::typeOf($arg));
             }
         }
     }
 }
 public function double_extension()
 {
     $this->assertEquals('application/x-tar-gz', MimeType::getByFilename('test.tar.gz'));
 }
 /**
  * Load an image
  *
  * @param   peer.URL source
  * @return  string[2] data and contenttype
  */
 public function load($source)
 {
     return [FileUtil::getContents(new File($source->getURL())), MimeType::getByFilename($source->getURL())];
 }