Skip to content

Fix that ESI/SSI processing can turn a "private" response "public" #26643

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 16, 2018

Conversation

mpdude
Copy link
Contributor

@mpdude mpdude commented Mar 22, 2018

Q A
Branch? 2.7
Bug fix? yes
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets
License MIT
Doc PR

Under the condition that

  • we are merging in at least one embedded response,
  • all embedded responses are public,
  • the main response is private and
  • all responses use expiration-based caching (note: no s-maxage on the main response)

... the resulting response will turn to Cache-Control: public.

The real issue is that when all responses use expiration-based caching, a combined max age is computed. This is set on the main response using Response::setSharedMaxAge(), which implicitly sets Cache-Control: public.

The fix provided in this PR solves the problem by applying the same logic to the main response that is applied for embedded responses, namely that responses with !Response::isCacheable() will make the resulting response have Cache-Control: private, no-cache, must-revalidate and have (s)max-age removed.

This makes the change easy to understand, but makes responses uncacheable too often. This is because the Response::isCacheable() method was written to determine whether it is safe for a shared cache to keep the response, which is not the case as soon as a private response is involved. This might be improved upon in another PR.

@mpdude
Copy link
Contributor Author

mpdude commented Mar 22, 2018

Ping @aschempp – you wrapped your head around the ResponseCacheStrategy lately, so you might want to comment.

@nicolas-grekas nicolas-grekas added this to the 2.7 milestone Mar 23, 2018
@aschempp
Copy link
Contributor

The fix looks somewhat correct to me, according to the PR title.

However, the correct solution would be to make the final response private (and not non-cacheable). But I guess you're aware of that and this PR is to disable caching in favor of incorrect caching.

@mpdude
Copy link
Contributor Author

mpdude commented Apr 11, 2018

@nicolas-grekas The appveyor test failed at

1) Symfony\Component\Console\Tests\Helper\ProcessHelperTest::testVariousProcessRuns with data set #2 ('  RUN  php -r "echo 42;"\n  OU...fully\n', 'php -r "echo 42;"', 4, null)
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
 '  RUN  php -r "echo 42;"
-  OUT  42
   RES  Command ran successfully
 '
C:\projects\symfony\src\Symfony\Component\Console\Tests\Helper\ProcessHelperTest.php:33
FAILURES!

Is that a known spurious test?

@fabpot fabpot force-pushed the fix-cache-public branch from e5a131b to 3d27b59 Compare April 16, 2018 17:48
@fabpot
Copy link
Member

fabpot commented Apr 16, 2018

Thank you @mpdude.

@fabpot fabpot merged commit 3d27b59 into symfony:2.7 Apr 16, 2018
fabpot added a commit that referenced this pull request Apr 16, 2018
…"public" (mpdude)

This PR was squashed before being merged into the 2.7 branch (closes #26643).

Discussion
----------

Fix that ESI/SSI processing can turn a "private" response "public"

| Q             | A
| ------------- | ---
| Branch?       | 2.7
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets |
| License       | MIT
| Doc PR        |

Under the condition that
* we are merging in at least one *embedded* response,
* all *embedded* responses are `public`,
* the *main* response is `private` and
* all responses use expiration-based caching (note: no `s-maxage` on the *main* response)

... the resulting response will turn to `Cache-Control: public`.

The real issue is that when all responses use expiration-based caching, a combined max age is computed. This is set on the *main* response using `Response::setSharedMaxAge()`, which implicitly sets `Cache-Control: public`.

The fix provided in this PR solves the problem by applying the same logic to the *main* response that is applied for *embedded* responses, namely that responses with `!Response::isCacheable()` will make the resulting response have `Cache-Control: private, no-cache, must-revalidate` and have `(s)max-age` removed.

This makes the change easy to understand, but makes responses uncacheable too often. This is because the `Response::isCacheable()` method was written to determine whether it is safe for a shared cache to keep the response, which is not the case as soon as a `private` response is involved. This might be improved upon in another PR.

Commits
-------

3d27b59 Fix that ESI/SSI processing can turn a \"private\" response \"public\"
@mpdude mpdude deleted the fix-cache-public branch April 17, 2018 08:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants