Skip to content

[HttpFoundation] Postpone setting the date header on a Response #14912

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

Conversation

jakzal
Copy link
Contributor

@jakzal jakzal commented Jun 8, 2015

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

The only risk of doing this is if someone called getDate() and the date header was not present, the date might be slightly different than the one sent with the headers.

getDate() could also set the date header first time it's requested (do a lazy initialisation).

@fabpot
Copy link
Member

fabpot commented Jun 8, 2015

There is also a slight BC break if someone access the Date header from the bag directly...

@fabpot
Copy link
Member

fabpot commented Jun 8, 2015

👍

@jakzal
Copy link
Contributor Author

jakzal commented Jun 9, 2015

ooops... HttpKernel tests are failing

@jakzal jakzal force-pushed the http-foundation/postpone-setting-the-date branch from b804502 to 6e85a3a Compare June 9, 2015 07:43
@jakzal
Copy link
Contributor Author

jakzal commented Jun 9, 2015

I've added lazy date header initialisation in getDate. It should fix the tests.

if (!$this->headers->has('Date')) {
$this->setDate(new \DateTime(null, new \DateTimeZone('UTC')));
}

return $this->headers->getDate('Date', new \DateTime());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is no point in adding a default here since it cannot trigger anymore. also this default could have the wrong timezone anyway.

@Tobion
Copy link
Contributor

Tobion commented Jun 9, 2015

There is a BC break for people who accessed $request->headers->getDate after request construction. The header will now not be set anymore. But I guess this is an edge case. People relying on it didn't respect the HeaderBag anyway which assumes headers are optional.

@fabpot
Copy link
Member

fabpot commented Jun 9, 2015

@Tobion That's the BC break I mentioned above, but I think we can ignore this use case. But of course, that's also why it should only be merged in 2.8 and not on earlier branches.

@Tobion
Copy link
Contributor

Tobion commented Jun 9, 2015

👍 apart from the changes I mentioned above

@jakzal jakzal force-pushed the http-foundation/postpone-setting-the-date branch from 6e85a3a to 2ad3b0d Compare June 9, 2015 16:58
@Tobion
Copy link
Contributor

Tobion commented Jun 9, 2015

Thanks Jakub.

@Tobion Tobion merged commit 2ad3b0d into symfony:2.8 Jun 9, 2015
Tobion added a commit that referenced this pull request Jun 9, 2015
… Response (jakzal)

This PR was merged into the 2.8 branch.

Discussion
----------

[HttpFoundation] Postpone setting the date header on a Response

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

The only risk of doing this is if someone called `getDate()` and the date header was not present, the date might be slightly different than the one sent with the headers.

`getDate()` could also set the date header first time it's requested (do a lazy initialisation).

Commits
-------

2ad3b0d [HttpFoundation] Postpone setting the date header on a Response
@jakzal jakzal deleted the http-foundation/postpone-setting-the-date branch June 9, 2015 18:45
@fabpot fabpot mentioned this pull request Nov 16, 2015
fabpot added a commit that referenced this pull request Mar 22, 2017
This PR was squashed before being merged into the 2.8 branch (closes #22036).

Discussion
----------

Set Date header in Response constructor already

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

Setting the `Date` header in the `Response` constructor has been removed in #14912 and changed to a more lazy approach in `getDate()`.

That way, methods like `getAge()`, `getTtl()` or `isFresh()` cause side effects as they eventually call `getDate()` and the Request "starts to age" once you call them.

I don't know if this would be a nice test, but current behaviour is

```php
        $response = new Response();
        $response->setSharedMaxAge(10);
        sleep(20);
        $this->assertTrue($response->isFresh());
        sleep(5);
        $this->assertTrue($response->isFresh());
        sleep(5);
        $this->assertFalse($response->isFresh());
```

A particular weird case is the `isCacheable()` method, because it calls `isFresh()` only under certain conditions, like particular status codes, no `ETag` present etc. This symptom is also described under "Cause of the problem" in #19390, however the problem is worked around there in other ways.

So, this PR suggests to effectively revert #14912.

Additionally, I'd like to suggest to move this special handling of the `Date` header into the `ResponseHeaderBag`. If the `ResponseHeaderBag` guards that we always have the `Date`, we would not need special logic in `sendHeaders()` and could also take care of #14912 (comment).

Commits
-------

3a7fa7e Set Date header in Response constructor already
symfony-splitter pushed a commit to symfony/http-foundation that referenced this pull request Mar 22, 2017
This PR was squashed before being merged into the 2.8 branch (closes #22036).

Discussion
----------

Set Date header in Response constructor already

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

Setting the `Date` header in the `Response` constructor has been removed in #14912 and changed to a more lazy approach in `getDate()`.

That way, methods like `getAge()`, `getTtl()` or `isFresh()` cause side effects as they eventually call `getDate()` and the Request "starts to age" once you call them.

I don't know if this would be a nice test, but current behaviour is

```php
        $response = new Response();
        $response->setSharedMaxAge(10);
        sleep(20);
        $this->assertTrue($response->isFresh());
        sleep(5);
        $this->assertTrue($response->isFresh());
        sleep(5);
        $this->assertFalse($response->isFresh());
```

A particular weird case is the `isCacheable()` method, because it calls `isFresh()` only under certain conditions, like particular status codes, no `ETag` present etc. This symptom is also described under "Cause of the problem" in #19390, however the problem is worked around there in other ways.

So, this PR suggests to effectively revert #14912.

Additionally, I'd like to suggest to move this special handling of the `Date` header into the `ResponseHeaderBag`. If the `ResponseHeaderBag` guards that we always have the `Date`, we would not need special logic in `sendHeaders()` and could also take care of symfony/symfony#14912 (comment).

Commits
-------

3a7fa7ede2 Set Date header in Response constructor already
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.

4 participants