Fossil SCM

Further changes trying to get ETags to work well. But as I type this, I feel like this design is not working out well and I am about ready to start over from scratch. This check-in is just to preserve work in case I want to come back to it later.

drh 2018-02-24 18:39 etags
Commit 02740c2c47ae7c35922e3333c4f63863835f28f06fde01664bfa7ced3da9138a
+6 -16
--- src/cgi.c
+++ src/cgi.c
@@ -258,12 +258,16 @@
258258
fprintf(g.httpOut, "Connection: close\r\n");
259259
fprintf(g.httpOut, "X-UA-Compatible: IE=edge\r\n");
260260
}else{
261261
fprintf(g.httpOut, "Status: %d %s\r\n", iReplyStatus, zReplyStatus);
262262
}
263
- zETag = etag_generate(-1);
264
- if( zETag ){
263
+ if( g.isConst ){
264
+ /* The g.isConst flag means that the result is immutable, even for
265
+ ** after configuration changes and/or rebuilds of the Fossil binary.
266
+ */
267
+ fprintf(g.httpOut, "Cache-Control: max-age=31536000\r\n");
268
+ }else if( (zETag = etag_generate(-1))!=0 ){
265269
fprintf(g.httpOut, "ETag: %s\r\n", zETag);
266270
fprintf(g.httpOut, "Cache-Control: max-age=%d\r\n", etag_maxage());
267271
}
268272
269273
if( blob_size(&extraHeader)>0 ){
@@ -286,24 +290,10 @@
286290
**
287291
** These headers are probably best added by the web server hosting fossil as
288292
** a CGI script.
289293
*/
290294
291
- if( g.isConst ){
292
- /* constant means that the input URL will _never_ generate anything
293
- ** else. In the case of attachments, the contents won't change because
294
- ** an attempt to change them generates a new attachment number. In the
295
- ** case of most /getfile calls for specific versions, the only way the
296
- ** content changes is if someone breaks the SCM. And if that happens, a
297
- ** stale cache is the least of the problem. So we provide an Expires
298
- ** header set to a reasonable period (default: one week).
299
- */
300
- fprintf(g.httpOut, "Cache-control: max-age=28800\r\n");
301
- }else{
302
- fprintf(g.httpOut, "Cache-control: no-cache\r\n");
303
- }
304
-
305295
/* Content intended for logged in users should only be cached in
306296
** the browser, not some shared location.
307297
*/
308298
fprintf(g.httpOut, "Content-Type: %s; charset=utf-8\r\n", zContentType);
309299
if( fossil_strcmp(zContentType,"application/x-fossil")==0 ){
310300
--- src/cgi.c
+++ src/cgi.c
@@ -258,12 +258,16 @@
258 fprintf(g.httpOut, "Connection: close\r\n");
259 fprintf(g.httpOut, "X-UA-Compatible: IE=edge\r\n");
260 }else{
261 fprintf(g.httpOut, "Status: %d %s\r\n", iReplyStatus, zReplyStatus);
262 }
263 zETag = etag_generate(-1);
264 if( zETag ){
 
 
 
 
265 fprintf(g.httpOut, "ETag: %s\r\n", zETag);
266 fprintf(g.httpOut, "Cache-Control: max-age=%d\r\n", etag_maxage());
267 }
268
269 if( blob_size(&extraHeader)>0 ){
@@ -286,24 +290,10 @@
286 **
287 ** These headers are probably best added by the web server hosting fossil as
288 ** a CGI script.
289 */
290
291 if( g.isConst ){
292 /* constant means that the input URL will _never_ generate anything
293 ** else. In the case of attachments, the contents won't change because
294 ** an attempt to change them generates a new attachment number. In the
295 ** case of most /getfile calls for specific versions, the only way the
296 ** content changes is if someone breaks the SCM. And if that happens, a
297 ** stale cache is the least of the problem. So we provide an Expires
298 ** header set to a reasonable period (default: one week).
299 */
300 fprintf(g.httpOut, "Cache-control: max-age=28800\r\n");
301 }else{
302 fprintf(g.httpOut, "Cache-control: no-cache\r\n");
303 }
304
305 /* Content intended for logged in users should only be cached in
306 ** the browser, not some shared location.
307 */
308 fprintf(g.httpOut, "Content-Type: %s; charset=utf-8\r\n", zContentType);
309 if( fossil_strcmp(zContentType,"application/x-fossil")==0 ){
310
--- src/cgi.c
+++ src/cgi.c
@@ -258,12 +258,16 @@
258 fprintf(g.httpOut, "Connection: close\r\n");
259 fprintf(g.httpOut, "X-UA-Compatible: IE=edge\r\n");
260 }else{
261 fprintf(g.httpOut, "Status: %d %s\r\n", iReplyStatus, zReplyStatus);
262 }
263 if( g.isConst ){
264 /* The g.isConst flag means that the result is immutable, even for
265 ** after configuration changes and/or rebuilds of the Fossil binary.
266 */
267 fprintf(g.httpOut, "Cache-Control: max-age=31536000\r\n");
268 }else if( (zETag = etag_generate(-1))!=0 ){
269 fprintf(g.httpOut, "ETag: %s\r\n", zETag);
270 fprintf(g.httpOut, "Cache-Control: max-age=%d\r\n", etag_maxage());
271 }
272
273 if( blob_size(&extraHeader)>0 ){
@@ -286,24 +290,10 @@
290 **
291 ** These headers are probably best added by the web server hosting fossil as
292 ** a CGI script.
293 */
294
 
 
 
 
 
 
 
 
 
 
 
 
 
 
295 /* Content intended for logged in users should only be cached in
296 ** the browser, not some shared location.
297 */
298 fprintf(g.httpOut, "Content-Type: %s; charset=utf-8\r\n", zContentType);
299 if( fossil_strcmp(zContentType,"application/x-fossil")==0 ){
300
+2 -4
--- src/doc.c
+++ src/doc.c
@@ -832,11 +832,11 @@
832832
214, 163, 146, 117, 238, 213, 154, 128, 151, 109, 84, 64, 217, 13,
833833
27, 10, 228, 39, 2, 235, 164, 168, 74, 8, 0, 59,
834834
};
835835
836836
/*
837
-** WEBPAGE: logo
837
+** WEBPAGE: logo config
838838
**
839839
** Return the logo image. This image is available to anybody who can see
840840
** the login page. It is designed for use in the upper left-hand corner
841841
** of the header.
842842
*/
@@ -850,11 +850,10 @@
850850
if( blob_size(&logo)==0 ){
851851
blob_init(&logo, (char*)aLogo, sizeof(aLogo));
852852
}
853853
cgi_set_content_type(zMime);
854854
cgi_set_content(&logo);
855
- g.isConst = 1;
856855
}
857856
858857
/*
859858
** The default background image: a 16x16 white GIF
860859
*/
@@ -867,11 +866,11 @@
867866
179, 62, 5, 0, 59,
868867
};
869868
870869
871870
/*
872
-** WEBPAGE: background
871
+** WEBPAGE: background const
873872
**
874873
** Return the background image. If no background image is defined, a
875874
** built-in 16x16 pixel white GIF is returned.
876875
*/
877876
void background_page(void){
@@ -884,11 +883,10 @@
884883
if( blob_size(&bgimg)==0 ){
885884
blob_init(&bgimg, (char*)aBackground, sizeof(aBackground));
886885
}
887886
cgi_set_content_type(zMime);
888887
cgi_set_content(&bgimg);
889
- g.isConst = 1;
890888
}
891889
892890
893891
/*
894892
** WEBPAGE: docsrch
895893
--- src/doc.c
+++ src/doc.c
@@ -832,11 +832,11 @@
832 214, 163, 146, 117, 238, 213, 154, 128, 151, 109, 84, 64, 217, 13,
833 27, 10, 228, 39, 2, 235, 164, 168, 74, 8, 0, 59,
834 };
835
836 /*
837 ** WEBPAGE: logo
838 **
839 ** Return the logo image. This image is available to anybody who can see
840 ** the login page. It is designed for use in the upper left-hand corner
841 ** of the header.
842 */
@@ -850,11 +850,10 @@
850 if( blob_size(&logo)==0 ){
851 blob_init(&logo, (char*)aLogo, sizeof(aLogo));
852 }
853 cgi_set_content_type(zMime);
854 cgi_set_content(&logo);
855 g.isConst = 1;
856 }
857
858 /*
859 ** The default background image: a 16x16 white GIF
860 */
@@ -867,11 +866,11 @@
867 179, 62, 5, 0, 59,
868 };
869
870
871 /*
872 ** WEBPAGE: background
873 **
874 ** Return the background image. If no background image is defined, a
875 ** built-in 16x16 pixel white GIF is returned.
876 */
877 void background_page(void){
@@ -884,11 +883,10 @@
884 if( blob_size(&bgimg)==0 ){
885 blob_init(&bgimg, (char*)aBackground, sizeof(aBackground));
886 }
887 cgi_set_content_type(zMime);
888 cgi_set_content(&bgimg);
889 g.isConst = 1;
890 }
891
892
893 /*
894 ** WEBPAGE: docsrch
895
--- src/doc.c
+++ src/doc.c
@@ -832,11 +832,11 @@
832 214, 163, 146, 117, 238, 213, 154, 128, 151, 109, 84, 64, 217, 13,
833 27, 10, 228, 39, 2, 235, 164, 168, 74, 8, 0, 59,
834 };
835
836 /*
837 ** WEBPAGE: logo config
838 **
839 ** Return the logo image. This image is available to anybody who can see
840 ** the login page. It is designed for use in the upper left-hand corner
841 ** of the header.
842 */
@@ -850,11 +850,10 @@
850 if( blob_size(&logo)==0 ){
851 blob_init(&logo, (char*)aLogo, sizeof(aLogo));
852 }
853 cgi_set_content_type(zMime);
854 cgi_set_content(&logo);
 
855 }
856
857 /*
858 ** The default background image: a 16x16 white GIF
859 */
@@ -867,11 +866,11 @@
866 179, 62, 5, 0, 59,
867 };
868
869
870 /*
871 ** WEBPAGE: background const
872 **
873 ** Return the background image. If no background image is defined, a
874 ** built-in 16x16 pixel white GIF is returned.
875 */
876 void background_page(void){
@@ -884,11 +883,10 @@
883 if( blob_size(&bgimg)==0 ){
884 blob_init(&bgimg, (char*)aBackground, sizeof(aBackground));
885 }
886 cgi_set_content_type(zMime);
887 cgi_set_content(&bgimg);
 
888 }
889
890
891 /*
892 ** WEBPAGE: docsrch
893
+8 -3
--- src/etag.c
+++ src/etag.c
@@ -129,12 +129,15 @@
129129
** is checked, and if it contains a compatible ETag, then a
130130
** 304 Not Modified return is generated and execution aborts. This
131131
** routine does not return if the 304 is generated.
132132
*/
133133
void etag_require(int code){
134
- if( (mEtag & code)==code ) return;
135
- mEtag |= code;
134
+ if( code==ETAG_CONST ){
135
+ mEtag = code;
136
+ }else{
137
+ mEtag |= code;
138
+ }
136139
etag_check();
137140
}
138141
void etag_require_hash(const char *zHash){
139142
if( zHash ){
140143
zEHash = zHash;
@@ -144,11 +147,13 @@
144147
}
145148
146149
/* Return an appropriate max-age.
147150
*/
148151
int etag_maxage(void){
149
- if( mEtag ) return 1;
152
+ if( mEtag & (ETAG_DYNAMIC|ETAG_COOKIE) ) return 0;
153
+ if( mEtag & (ETAG_DATA|ETAG_HASH) ) return 60;
154
+ if( mEtag & (ETAG_CONFIG) ) return 300;
150155
return 3600*24;
151156
}
152157
153158
/* Generate an appropriate ETags value that captures all requirements.
154159
** Space is obtained from fossil_malloc().
155160
--- src/etag.c
+++ src/etag.c
@@ -129,12 +129,15 @@
129 ** is checked, and if it contains a compatible ETag, then a
130 ** 304 Not Modified return is generated and execution aborts. This
131 ** routine does not return if the 304 is generated.
132 */
133 void etag_require(int code){
134 if( (mEtag & code)==code ) return;
135 mEtag |= code;
 
 
 
136 etag_check();
137 }
138 void etag_require_hash(const char *zHash){
139 if( zHash ){
140 zEHash = zHash;
@@ -144,11 +147,13 @@
144 }
145
146 /* Return an appropriate max-age.
147 */
148 int etag_maxage(void){
149 if( mEtag ) return 1;
 
 
150 return 3600*24;
151 }
152
153 /* Generate an appropriate ETags value that captures all requirements.
154 ** Space is obtained from fossil_malloc().
155
--- src/etag.c
+++ src/etag.c
@@ -129,12 +129,15 @@
129 ** is checked, and if it contains a compatible ETag, then a
130 ** 304 Not Modified return is generated and execution aborts. This
131 ** routine does not return if the 304 is generated.
132 */
133 void etag_require(int code){
134 if( code==ETAG_CONST ){
135 mEtag = code;
136 }else{
137 mEtag |= code;
138 }
139 etag_check();
140 }
141 void etag_require_hash(const char *zHash){
142 if( zHash ){
143 zEHash = zHash;
@@ -144,11 +147,13 @@
147 }
148
149 /* Return an appropriate max-age.
150 */
151 int etag_maxage(void){
152 if( mEtag & (ETAG_DYNAMIC|ETAG_COOKIE) ) return 0;
153 if( mEtag & (ETAG_DATA|ETAG_HASH) ) return 60;
154 if( mEtag & (ETAG_CONFIG) ) return 300;
155 return 3600*24;
156 }
157
158 /* Generate an appropriate ETags value that captures all requirements.
159 ** Space is obtained from fossil_malloc().
160
+2
--- src/info.c
+++ src/info.c
@@ -1688,13 +1688,15 @@
16881688
}
16891689
login_check_credentials();
16901690
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
16911691
if( rid==0 ) fossil_redirect_home();
16921692
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
1693
+#if 0
16931694
if( fossil_strcmp(P("name"), zUuid)==0 && login_is_nobody() ){
16941695
g.isConst = 1;
16951696
}
1697
+#endif
16961698
free(zUuid);
16971699
zMime = P("m");
16981700
if( zMime==0 ){
16991701
char *zFName = db_text(0, "SELECT filename.name FROM mlink, filename"
17001702
" WHERE mlink.fid=%d"
17011703
--- src/info.c
+++ src/info.c
@@ -1688,13 +1688,15 @@
1688 }
1689 login_check_credentials();
1690 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1691 if( rid==0 ) fossil_redirect_home();
1692 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
 
1693 if( fossil_strcmp(P("name"), zUuid)==0 && login_is_nobody() ){
1694 g.isConst = 1;
1695 }
 
1696 free(zUuid);
1697 zMime = P("m");
1698 if( zMime==0 ){
1699 char *zFName = db_text(0, "SELECT filename.name FROM mlink, filename"
1700 " WHERE mlink.fid=%d"
1701
--- src/info.c
+++ src/info.c
@@ -1688,13 +1688,15 @@
1688 }
1689 login_check_credentials();
1690 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1691 if( rid==0 ) fossil_redirect_home();
1692 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
1693 #if 0
1694 if( fossil_strcmp(P("name"), zUuid)==0 && login_is_nobody() ){
1695 g.isConst = 1;
1696 }
1697 #endif
1698 free(zUuid);
1699 zMime = P("m");
1700 if( zMime==0 ){
1701 char *zFName = db_text(0, "SELECT filename.name FROM mlink, filename"
1702 " WHERE mlink.fid=%d"
1703
+11 -5
--- src/style.c
+++ src/style.c
@@ -780,11 +780,11 @@
780780
blob_reset(&css);
781781
}
782782
783783
784784
/*
785
-** WEBPAGE: style.css
785
+** WEBPAGE: style.css config
786786
**
787787
** Return the style sheet.
788788
*/
789789
void page_style_css(void){
790790
Blob css;
@@ -822,26 +822,28 @@
822822
Th_Store("secureurl", login_wants_https_redirect()? g.zHttpsURL: g.zBaseURL);
823823
Th_Store("home", g.zTop);
824824
image_url_var("logo");
825825
image_url_var("background");
826826
Th_Render(blob_str(&css));
827
-
828
- /* Tell CGI that the content returned by this page is considered cacheable */
829
- g.isConst = 1;
830827
}
831828
832829
/*
833830
** WEBPAGE: builtin
834831
** URL: builtin/FILENAME
835832
**
836833
** Return the built-in text given by FILENAME. This is used internally
837834
** by many Fossil web pages to load built-in javascript files.
835
+**
836
+** If the id= query parameter is present, then Fossil assumes that the
837
+** result is immutable and sets a very large cache retention time (1 year).
838838
*/
839839
void page_builtin_text(void){
840840
Blob out;
841841
const char *zName = P("name");
842842
const char *zTxt = 0;
843
+ const char *zId = P("id");
844
+ int nId;
843845
if( zName ) zTxt = builtin_text(zName);
844846
if( zTxt==0 ){
845847
cgi_set_status(404, "Not Found");
846848
@ File "%h(zName)" not found
847849
return;
@@ -849,13 +851,17 @@
849851
if( sqlite3_strglob("*.js", zName)==0 ){
850852
cgi_set_content_type("application/javascript");
851853
}else{
852854
cgi_set_content_type("text/plain");
853855
}
856
+ if( zId && (nId = (int)strlen(zId))>=8 && strncmp(zId,MANIFEST_UUID,nId)==0 ){
857
+ g.isConst = 1;
858
+ }else{
859
+ etag_require(ETAG_CONST);
860
+ }
854861
blob_init(&out, zTxt, -1);
855862
cgi_set_content(&out);
856
- g.isConst = 1;
857863
}
858864
859865
860866
/*
861867
** WEBPAGE: test_env
862868
--- src/style.c
+++ src/style.c
@@ -780,11 +780,11 @@
780 blob_reset(&css);
781 }
782
783
784 /*
785 ** WEBPAGE: style.css
786 **
787 ** Return the style sheet.
788 */
789 void page_style_css(void){
790 Blob css;
@@ -822,26 +822,28 @@
822 Th_Store("secureurl", login_wants_https_redirect()? g.zHttpsURL: g.zBaseURL);
823 Th_Store("home", g.zTop);
824 image_url_var("logo");
825 image_url_var("background");
826 Th_Render(blob_str(&css));
827
828 /* Tell CGI that the content returned by this page is considered cacheable */
829 g.isConst = 1;
830 }
831
832 /*
833 ** WEBPAGE: builtin
834 ** URL: builtin/FILENAME
835 **
836 ** Return the built-in text given by FILENAME. This is used internally
837 ** by many Fossil web pages to load built-in javascript files.
 
 
 
838 */
839 void page_builtin_text(void){
840 Blob out;
841 const char *zName = P("name");
842 const char *zTxt = 0;
 
 
843 if( zName ) zTxt = builtin_text(zName);
844 if( zTxt==0 ){
845 cgi_set_status(404, "Not Found");
846 @ File "%h(zName)" not found
847 return;
@@ -849,13 +851,17 @@
849 if( sqlite3_strglob("*.js", zName)==0 ){
850 cgi_set_content_type("application/javascript");
851 }else{
852 cgi_set_content_type("text/plain");
853 }
 
 
 
 
 
854 blob_init(&out, zTxt, -1);
855 cgi_set_content(&out);
856 g.isConst = 1;
857 }
858
859
860 /*
861 ** WEBPAGE: test_env
862
--- src/style.c
+++ src/style.c
@@ -780,11 +780,11 @@
780 blob_reset(&css);
781 }
782
783
784 /*
785 ** WEBPAGE: style.css config
786 **
787 ** Return the style sheet.
788 */
789 void page_style_css(void){
790 Blob css;
@@ -822,26 +822,28 @@
822 Th_Store("secureurl", login_wants_https_redirect()? g.zHttpsURL: g.zBaseURL);
823 Th_Store("home", g.zTop);
824 image_url_var("logo");
825 image_url_var("background");
826 Th_Render(blob_str(&css));
 
 
 
827 }
828
829 /*
830 ** WEBPAGE: builtin
831 ** URL: builtin/FILENAME
832 **
833 ** Return the built-in text given by FILENAME. This is used internally
834 ** by many Fossil web pages to load built-in javascript files.
835 **
836 ** If the id= query parameter is present, then Fossil assumes that the
837 ** result is immutable and sets a very large cache retention time (1 year).
838 */
839 void page_builtin_text(void){
840 Blob out;
841 const char *zName = P("name");
842 const char *zTxt = 0;
843 const char *zId = P("id");
844 int nId;
845 if( zName ) zTxt = builtin_text(zName);
846 if( zTxt==0 ){
847 cgi_set_status(404, "Not Found");
848 @ File "%h(zName)" not found
849 return;
@@ -849,13 +851,17 @@
851 if( sqlite3_strglob("*.js", zName)==0 ){
852 cgi_set_content_type("application/javascript");
853 }else{
854 cgi_set_content_type("text/plain");
855 }
856 if( zId && (nId = (int)strlen(zId))>=8 && strncmp(zId,MANIFEST_UUID,nId)==0 ){
857 g.isConst = 1;
858 }else{
859 etag_require(ETAG_CONST);
860 }
861 blob_init(&out, zTxt, -1);
862 cgi_set_content(&out);
 
863 }
864
865
866 /*
867 ** WEBPAGE: test_env
868

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button