Repository: symfony/symfony
File: src/Symfony/Component/HttpKernel/HttpCache/Store.php (PHP)

Code before:
        @chmod($path, 0666 & ~umask());

        return true;
    }

    public function getPath(string $key): string
    {
        return $this->root.\DIRECTORY_SEPARATOR.substr($key, 0, 2).\DIRECTORY_SEPARATOR.substr($key, 2, 2).\DIRECTORY_SEPARATOR.substr($key, 4, 2).\DIRECTORY_SEPARATOR.substr($key, 6);
    }

    /**
     * Generates a cache key for the given Request.
     *
     * This method should return a key that must only depend on a
     * normalized version of the request URI.
     *
     * If the same URI can have more than one representation, based on some
     * headers, use a Vary header to indicate them, and each representation will
     * be stored independently under the same cache key.
     */
    protected function generateCacheKey(Request $request): string
    {
        $key = $request->getUri();

        if ('QUERY' === $request->getMethod()) {
            $key .= $request->getContent();
        }

        return 'md'.hash('sha256', $key);
    }

    /**
     * Returns a cache key for the given Request.
     */
    private function getCacheKey(Request $request): string
    {
        if (isset($this->keyCache[$request])) {
            return $this->keyCache[$request];
        }

        return $this->keyCache[$request] = $this->generateCacheKey($request);
    }

    /**
     * Persists the Request HTTP headers.
     */
    private function persistRequest(Request $request): array
    {
        return $request->headers->all();
    }


Review comment (performance):
We should probably inject a delimiter between the URI and the content, or hash them separately, to avoid 2 queries to share the same cache keys by moving a prefix of the content into a suffix of the URI instead.

Code after:
        @chmod($path, 0o666 & ~umask());

        return true;
    }

    public function getPath(string $key): string
    {
        return $this->root.\DIRECTORY_SEPARATOR.substr($key, 0, 2).\DIRECTORY_SEPARATOR.substr($key, 2, 2).\DIRECTORY_SEPARATOR.substr($key, 4, 2).\DIRECTORY_SEPARATOR.substr($key, 6);
    }

    /**
     * Generates a cache key for the given Request.
     *
     * This method should return a key that must only depend on a
     * normalized version of the request URI.
     *
     * If the same URI can have more than one representation, based on some
     * headers, use a Vary header to indicate them, and each representation will
     * be stored independently under the same cache key.
     */
    protected function generateCacheKey(Request $request): string
    {
        $key = $request->getUri();

        if ('QUERY' === $request->getMethod()) {
            // add null byte to separate the URI from the body and avoid boundary collisions
            // which could lead to cache poisoning
            $key .= "\0".$request->getContent();
        }

        return 'md'.hash('sha256', $key);
    }

    /**
     * Returns a cache key for the given Request.
     */
    private function getCacheKey(Request $request): string
    {
        if (isset($this->keyCache[$request])) {
            return $this->keyCache[$request];
        }

        return $this->keyCache[$request] = $this->generateCacheKey($request);
    }

    /**
     * Persists the Request HTTP headers.
     */
    private function persistRequest(Request $request): array
    {
        return $request->headers->all();