After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 695121 - SoupCache: conditional requests do not update headers in cache
SoupCache: conditional requests do not update headers in cache
Status: RESOLVED FIXED
Product: libsoup
Classification: Core
Component: Misc
2.41.x
Other Linux
: Normal normal
: ---
Assigned To: Sergio Villar
libsoup-maint@gnome.bugs
Depends on:
Blocks:
 
 
Reported: 2013-03-04 12:46 UTC by Sergio Villar
Modified: 2013-03-05 15:17 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Replace old headers (3.29 KB, patch)
2013-03-04 12:49 UTC, Sergio Villar
needs-work Details | Review
Update cached headers on revalidations (17.08 KB, patch)
2013-03-04 17:25 UTC, Sergio Villar
reviewed Details | Review
Update cached headers on revalidations (17.14 KB, patch)
2013-03-05 09:06 UTC, Sergio Villar
committed Details | Review

Description Sergio Villar 2013-03-04 12:46:01 UTC
A HTTP cache must replace the already cached headers with their new versions (for example when revalidating resources) instead of copying them.
Comment 1 Sergio Villar 2013-03-04 12:49:11 UTC
Created attachment 237972 [details] [review]
Replace old headers
Comment 2 Dan Winship 2013-03-04 13:50:54 UTC
Comment on attachment 237972 [details] [review]
Replace old headers

> static void
>-copy_headers (const char *name, const char *value, SoupMessageHeaders *headers)
>+replace_headers (const char *name, const char *value, SoupMessageHeaders *headers)
> {
>-	soup_message_headers_append (headers, name, value);
>+	soup_message_headers_replace (headers, name, value);
> }

>-	soup_message_headers_foreach (source, (SoupMessageHeadersForeachFunc) copy_headers, destination);
>+	soup_message_headers_foreach (source, (SoupMessageHeadersForeachFunc) replace_headers, destination);

This won't work, because if a header appears multiple times in source (eg, Set-Cookie), only the last appearance of it will end up in destination.

You need to do two passes; first remove all the headers in destination that are also in source, then copy all the headers from source to destination like before.
Comment 3 Sergio Villar 2013-03-04 14:41:45 UTC
(In reply to comment #2)
> (From update of attachment 237972 [details] [review])
> > static void
> >-copy_headers (const char *name, const char *value, SoupMessageHeaders *headers)
> >+replace_headers (const char *name, const char *value, SoupMessageHeaders *headers)
> > {
> >-	soup_message_headers_append (headers, name, value);
> >+	soup_message_headers_replace (headers, name, value);
> > }
> 
> >-	soup_message_headers_foreach (source, (SoupMessageHeadersForeachFunc) copy_headers, destination);
> >+	soup_message_headers_foreach (source, (SoupMessageHeadersForeachFunc) replace_headers, destination);
> 
> This won't work, because if a header appears multiple times in source (eg,
> Set-Cookie), only the last appearance of it will end up in destination.

Good point.
Comment 4 Sergio Villar 2013-03-04 17:25:10 UTC
Created attachment 238021 [details] [review]
Update cached headers on revalidations

So this allowed me to review a bit how headers were updated and I realized that we weren't updating them after conditional requests, this was only done by revalidations started by libsoup clients. That's why there was a test in cache-test.c that was not working (the test was ok Dan the problem was the cache).

This patch fixes that problem, properly updates the values for the cached headers and provides a new test for it.

I also noticed that two computed values, freshness_lifetime and must_revalidate, were not reset in the case that the server stopped returning them to us. They are now initialized at the beginning of soup_cache_entry_set_freshness()(they'll get the proper value if the server specifies the corresponding headers).
Comment 5 Dan Winship 2013-03-04 20:05:57 UTC
Comment on attachment 238021 [details] [review]
Update cached headers on revalidations

>-	if (msg->status_code == SOUP_STATUS_NOT_MODIFIED) {
>-		SoupCache *cache = (SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE);
>+	cache = (SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE);
>+	soup_cache_update_from_conditional_request (cache, msg);
> 
>+	if (msg->status_code == SOUP_STATUS_NOT_MODIFIED) {

The update_from_conditional_request should happen inside the if body shouldn't it? In particular, if it's an error status code, or a redirection, we shouldn't update the cache with its headers.


everything else looks good, and yay for more tests
Comment 6 Sergio Villar 2013-03-05 08:30:20 UTC
(In reply to comment #5)
> (From update of attachment 238021 [details] [review])
> >-	if (msg->status_code == SOUP_STATUS_NOT_MODIFIED) {
> >-		SoupCache *cache = (SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE);
> >+	cache = (SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE);
> >+	soup_cache_update_from_conditional_request (cache, msg);
> > 
> >+	if (msg->status_code == SOUP_STATUS_NOT_MODIFIED) {
> 
> The update_from_conditional_request should happen inside the if body shouldn't
> it? In particular, if it's an error status code, or a redirection, we shouldn't
> update the cache with its headers.

Yep you're right
 
 
> everything else looks good, and yay for more tests
Comment 7 Sergio Villar 2013-03-05 09:06:08 UTC
Created attachment 238100 [details] [review]
Update cached headers on revalidations

I left the code before the "== 304" check because we need to update the being_validated flag anyway. The difference is that soup_cache_update_from_conditional_request() won't update the headers for non 304 responses.
Comment 8 Dan Winship 2013-03-05 13:12:54 UTC
Comment on attachment 238100 [details] [review]
Update cached headers on revalidations

great
Comment 9 Sergio Villar 2013-03-05 15:17:29 UTC
Committed in master 74f914e2