Fossil SCM

Experimental support for "Range:" headers in HTTP requests.

drh 2020-03-15 15:22 trunk
Commit 37c615ad29935b47c91aacca9deed1a704e9534a1553ff04c89870731a870d17
1 file changed +29 -4
+29 -4
--- src/cgi.c
+++ src/cgi.c
@@ -178,10 +178,12 @@
178178
*/
179179
static const char *zContentType = "text/html"; /* Content type of the reply */
180180
static const char *zReplyStatus = "OK"; /* Reply status description */
181181
static int iReplyStatus = 200; /* Reply status code */
182182
static Blob extraHeader = BLOB_INITIALIZER; /* Extra header text */
183
+static int rangeStart = 0;
184
+static int rangeEnd = 0;
183185
184186
/*
185187
** Set the reply content type
186188
*/
187189
void cgi_set_content_type(const char *zType){
@@ -272,10 +274,13 @@
272274
iReplyStatus = 200;
273275
zReplyStatus = "OK";
274276
}
275277
276278
if( g.fullHttpReply ){
279
+ if( rangeEnd>rangeStart && iReplyStatus==200 ){
280
+ iReplyStatus = 206;
281
+ }
277282
fprintf(g.httpOut, "HTTP/1.0 %d %s\r\n", iReplyStatus, zReplyStatus);
278283
fprintf(g.httpOut, "Date: %s\r\n", cgi_rfc822_datestamp(time(0)));
279284
fprintf(g.httpOut, "Connection: close\r\n");
280285
fprintf(g.httpOut, "X-UA-Compatible: IE=edge\r\n");
281286
}else{
@@ -325,12 +330,12 @@
325330
if( fossil_strcmp(zContentType,"application/x-fossil")==0 ){
326331
cgi_combine_header_and_body();
327332
blob_compress(&cgiContent[0], &cgiContent[0]);
328333
}
329334
330
- if( iReplyStatus != 304 ) {
331
- if( is_gzippable() ){
335
+ if( iReplyStatus!=304 ) {
336
+ if( is_gzippable() && iReplyStatus!=206 ){
332337
int i;
333338
gzip_begin(0);
334339
for( i=0; i<2; i++ ){
335340
int size = blob_size(&cgiContent[i]);
336341
if( size>0 ) gzip_step(blob_buffer(&cgiContent[i]), size);
@@ -339,10 +344,15 @@
339344
gzip_finish(&cgiContent[0]);
340345
fprintf(g.httpOut, "Content-Encoding: gzip\r\n");
341346
fprintf(g.httpOut, "Vary: Accept-Encoding\r\n");
342347
}
343348
total_size = blob_size(&cgiContent[0]) + blob_size(&cgiContent[1]);
349
+ if( iReplyStatus==206 ){
350
+ fprintf(g.httpOut, "Content-Range: bytes %d-%d/%d\r\n",
351
+ rangeStart, rangeEnd, total_size);
352
+ total_size = rangeEnd - rangeStart;
353
+ }
344354
fprintf(g.httpOut, "Content-Length: %d\r\n", total_size);
345355
}else{
346356
total_size = 0;
347357
}
348358
fprintf(g.httpOut, "\r\n");
@@ -350,12 +360,20 @@
350360
&& fossil_strcmp(P("REQUEST_METHOD"),"HEAD")!=0
351361
){
352362
int i, size;
353363
for(i=0; i<2; i++){
354364
size = blob_size(&cgiContent[i]);
355
- if( size>0 ){
356
- fwrite(blob_buffer(&cgiContent[i]), 1, size, g.httpOut);
365
+ if( size<=rangeStart ){
366
+ rangeStart -= size;
367
+ }else{
368
+ int n = size - rangeStart;
369
+ if( n>total_size ){
370
+ n = total_size;
371
+ }
372
+ fwrite(blob_buffer(&cgiContent[i])+rangeStart, 1, n, g.httpOut);
373
+ rangeStart = 0;
374
+ total_size -= n;
357375
}
358376
}
359377
}
360378
fflush(g.httpOut);
361379
CGIDEBUG(("-------- END cgi ---------\n"));
@@ -1658,10 +1676,17 @@
16581676
}else if( fossil_strcmp(zFieldName,"x-forwarded-for:")==0 ){
16591677
const char *zIpAddr = cgi_accept_forwarded_for(zVal);
16601678
if( zIpAddr!=0 ){
16611679
g.zIpAddr = mprintf("%s", zIpAddr);
16621680
cgi_replace_parameter("REMOTE_ADDR", g.zIpAddr);
1681
+ }
1682
+ }else if( fossil_strcmp(zFieldName,"range:")==0 ){
1683
+ int x1 = 0;
1684
+ int x2 = 0;
1685
+ if( sscanf(zVal,"bytes=%d-%d",&x1,&x2)==2 && x1>=0 && x1<=x2 ){
1686
+ rangeStart = x1;
1687
+ rangeEnd = x2+1;
16631688
}
16641689
}
16651690
}
16661691
cgi_init();
16671692
cgi_trace(0);
16681693
--- src/cgi.c
+++ src/cgi.c
@@ -178,10 +178,12 @@
178 */
179 static const char *zContentType = "text/html"; /* Content type of the reply */
180 static const char *zReplyStatus = "OK"; /* Reply status description */
181 static int iReplyStatus = 200; /* Reply status code */
182 static Blob extraHeader = BLOB_INITIALIZER; /* Extra header text */
 
 
183
184 /*
185 ** Set the reply content type
186 */
187 void cgi_set_content_type(const char *zType){
@@ -272,10 +274,13 @@
272 iReplyStatus = 200;
273 zReplyStatus = "OK";
274 }
275
276 if( g.fullHttpReply ){
 
 
 
277 fprintf(g.httpOut, "HTTP/1.0 %d %s\r\n", iReplyStatus, zReplyStatus);
278 fprintf(g.httpOut, "Date: %s\r\n", cgi_rfc822_datestamp(time(0)));
279 fprintf(g.httpOut, "Connection: close\r\n");
280 fprintf(g.httpOut, "X-UA-Compatible: IE=edge\r\n");
281 }else{
@@ -325,12 +330,12 @@
325 if( fossil_strcmp(zContentType,"application/x-fossil")==0 ){
326 cgi_combine_header_and_body();
327 blob_compress(&cgiContent[0], &cgiContent[0]);
328 }
329
330 if( iReplyStatus != 304 ) {
331 if( is_gzippable() ){
332 int i;
333 gzip_begin(0);
334 for( i=0; i<2; i++ ){
335 int size = blob_size(&cgiContent[i]);
336 if( size>0 ) gzip_step(blob_buffer(&cgiContent[i]), size);
@@ -339,10 +344,15 @@
339 gzip_finish(&cgiContent[0]);
340 fprintf(g.httpOut, "Content-Encoding: gzip\r\n");
341 fprintf(g.httpOut, "Vary: Accept-Encoding\r\n");
342 }
343 total_size = blob_size(&cgiContent[0]) + blob_size(&cgiContent[1]);
 
 
 
 
 
344 fprintf(g.httpOut, "Content-Length: %d\r\n", total_size);
345 }else{
346 total_size = 0;
347 }
348 fprintf(g.httpOut, "\r\n");
@@ -350,12 +360,20 @@
350 && fossil_strcmp(P("REQUEST_METHOD"),"HEAD")!=0
351 ){
352 int i, size;
353 for(i=0; i<2; i++){
354 size = blob_size(&cgiContent[i]);
355 if( size>0 ){
356 fwrite(blob_buffer(&cgiContent[i]), 1, size, g.httpOut);
 
 
 
 
 
 
 
 
357 }
358 }
359 }
360 fflush(g.httpOut);
361 CGIDEBUG(("-------- END cgi ---------\n"));
@@ -1658,10 +1676,17 @@
1658 }else if( fossil_strcmp(zFieldName,"x-forwarded-for:")==0 ){
1659 const char *zIpAddr = cgi_accept_forwarded_for(zVal);
1660 if( zIpAddr!=0 ){
1661 g.zIpAddr = mprintf("%s", zIpAddr);
1662 cgi_replace_parameter("REMOTE_ADDR", g.zIpAddr);
 
 
 
 
 
 
 
1663 }
1664 }
1665 }
1666 cgi_init();
1667 cgi_trace(0);
1668
--- src/cgi.c
+++ src/cgi.c
@@ -178,10 +178,12 @@
178 */
179 static const char *zContentType = "text/html"; /* Content type of the reply */
180 static const char *zReplyStatus = "OK"; /* Reply status description */
181 static int iReplyStatus = 200; /* Reply status code */
182 static Blob extraHeader = BLOB_INITIALIZER; /* Extra header text */
183 static int rangeStart = 0;
184 static int rangeEnd = 0;
185
186 /*
187 ** Set the reply content type
188 */
189 void cgi_set_content_type(const char *zType){
@@ -272,10 +274,13 @@
274 iReplyStatus = 200;
275 zReplyStatus = "OK";
276 }
277
278 if( g.fullHttpReply ){
279 if( rangeEnd>rangeStart && iReplyStatus==200 ){
280 iReplyStatus = 206;
281 }
282 fprintf(g.httpOut, "HTTP/1.0 %d %s\r\n", iReplyStatus, zReplyStatus);
283 fprintf(g.httpOut, "Date: %s\r\n", cgi_rfc822_datestamp(time(0)));
284 fprintf(g.httpOut, "Connection: close\r\n");
285 fprintf(g.httpOut, "X-UA-Compatible: IE=edge\r\n");
286 }else{
@@ -325,12 +330,12 @@
330 if( fossil_strcmp(zContentType,"application/x-fossil")==0 ){
331 cgi_combine_header_and_body();
332 blob_compress(&cgiContent[0], &cgiContent[0]);
333 }
334
335 if( iReplyStatus!=304 ) {
336 if( is_gzippable() && iReplyStatus!=206 ){
337 int i;
338 gzip_begin(0);
339 for( i=0; i<2; i++ ){
340 int size = blob_size(&cgiContent[i]);
341 if( size>0 ) gzip_step(blob_buffer(&cgiContent[i]), size);
@@ -339,10 +344,15 @@
344 gzip_finish(&cgiContent[0]);
345 fprintf(g.httpOut, "Content-Encoding: gzip\r\n");
346 fprintf(g.httpOut, "Vary: Accept-Encoding\r\n");
347 }
348 total_size = blob_size(&cgiContent[0]) + blob_size(&cgiContent[1]);
349 if( iReplyStatus==206 ){
350 fprintf(g.httpOut, "Content-Range: bytes %d-%d/%d\r\n",
351 rangeStart, rangeEnd, total_size);
352 total_size = rangeEnd - rangeStart;
353 }
354 fprintf(g.httpOut, "Content-Length: %d\r\n", total_size);
355 }else{
356 total_size = 0;
357 }
358 fprintf(g.httpOut, "\r\n");
@@ -350,12 +360,20 @@
360 && fossil_strcmp(P("REQUEST_METHOD"),"HEAD")!=0
361 ){
362 int i, size;
363 for(i=0; i<2; i++){
364 size = blob_size(&cgiContent[i]);
365 if( size<=rangeStart ){
366 rangeStart -= size;
367 }else{
368 int n = size - rangeStart;
369 if( n>total_size ){
370 n = total_size;
371 }
372 fwrite(blob_buffer(&cgiContent[i])+rangeStart, 1, n, g.httpOut);
373 rangeStart = 0;
374 total_size -= n;
375 }
376 }
377 }
378 fflush(g.httpOut);
379 CGIDEBUG(("-------- END cgi ---------\n"));
@@ -1658,10 +1676,17 @@
1676 }else if( fossil_strcmp(zFieldName,"x-forwarded-for:")==0 ){
1677 const char *zIpAddr = cgi_accept_forwarded_for(zVal);
1678 if( zIpAddr!=0 ){
1679 g.zIpAddr = mprintf("%s", zIpAddr);
1680 cgi_replace_parameter("REMOTE_ADDR", g.zIpAddr);
1681 }
1682 }else if( fossil_strcmp(zFieldName,"range:")==0 ){
1683 int x1 = 0;
1684 int x2 = 0;
1685 if( sscanf(zVal,"bytes=%d-%d",&x1,&x2)==2 && x1>=0 && x1<=x2 ){
1686 rangeStart = x1;
1687 rangeEnd = x2+1;
1688 }
1689 }
1690 }
1691 cgi_init();
1692 cgi_trace(0);
1693

Keyboard Shortcuts

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