public function process(DispatchRequest $dispatch)
 {
     if (!$dispatch->isMaster()) {
         return $dispatch->proceed();
     }
     $request = $dispatch->getHttpRequest();
     $path = $request->getPathInfo();
     $m = NULL;
     if (!preg_match("'^_res/+(.+)\$'i", $path, $m)) {
         return $dispatch->proceed();
     }
     $path = $m[1];
     if ('app/' === substr($path, 0, 4)) {
         $resource = 'k2://app/' . substr($path, 4);
     } else {
         $parts = explode('/', $path, 2);
         if (count($parts) !== 2) {
             return new HttpResponse(Http::CODE_NOT_FOUND);
         }
         $resource = 'k2://' . $parts[0] . '/' . $parts[1];
     }
     if (!is_file($resource)) {
         return new HttpResponse(Http::CODE_NOT_FOUND);
     }
     if (!$this->publisher->isPublic($resource)) {
         return new HttpResponse(Http::CODE_FORBIDDEN);
     }
     $response = new HttpResponse();
     // Conditional caching:
     $etag = sprintf('"%x-%x"', filemtime($resource), filesize($resource));
     $response->setHeader('Access-Control-Allow-Origin', '*');
     $response->setHeader('Cache-Control', 'public, max-age=7200');
     $response->setHeader('ETag', $etag);
     $response->setHeader(new ExpiresHeader(new \DateTimeImmutable('@' . (time() + 7200))));
     if ($etag === $request->getHeader('If-None-Match', '')) {
         $response->setStatus(Http::CODE_NOT_MODIFIED);
         return $response;
     }
     $mediaType = new MediaType(Filesystem::guessMimeTypeFromFilename($resource));
     $response->setHeader('X-Content-Type-Options', 'nosniff');
     if ($mediaType->isType('text')) {
         $response->setHeader('Content-Type', $mediaType . '; charset="utf-8"');
     } else {
         $response->setHeader('Content-Type', (string) $mediaType);
     }
     $response->setEntity(new FileEntity(new \SplFileInfo($resource)));
     return $response;
 }