... | ... |
@@ -31,6 +31,7 @@ |
31 | 31 |
#define BUFBLOCKBLOCK 256 |
32 | 32 |
#define POSTBLOCK 16 |
33 | 33 |
#define ALIVETIMEOUT 15 |
34 |
+#define MAXETAGSIZE 127 |
|
34 | 35 |
|
35 | 36 |
typedef struct wk_post { |
36 | 37 |
char *name; |
... | ... |
@@ -67,6 +68,7 @@ typedef struct wk_client { |
67 | 68 |
int pendingpost; |
68 | 69 |
int inpostvar; |
69 | 70 |
int cookiebufid; |
71 |
+ char etag[MAXETAGSIZE+1]; |
|
70 | 72 |
time_t lastio; |
71 | 73 |
} wk_client; |
72 | 74 |
|
... | ... |
@@ -117,6 +119,7 @@ static int wk_postadd(_wk *web, wk_client *client,char *varname, char *tofile); |
117 | 119 |
static int wk_postset(_wk *web, wk_client *client,char *varname, char *data, int datalen); |
118 | 120 |
static char *wk_postget(_wk *web, wk_client *client,char *varname, int *isfile); |
119 | 121 |
static int wk_postfree(_wk *web, wk_client *client); |
122 |
+static int wk_etagnotmodified(_wk *web, wk_client *client); |
|
120 | 123 |
|
121 | 124 |
#ifdef WK_DEBUG_IO |
122 | 125 |
#define DEBUG_IN_PRE { int sbp=sbuf_count(in); |
... | ... |
@@ -438,6 +441,22 @@ wk_serve_cookieadd(wk *paramweb, int connid, char *cookiename, char *value, char |
438 | 441 |
return(0); |
439 | 442 |
} |
440 | 443 |
|
444 |
+int |
|
445 |
+wk_serve_etagset(wk *paramweb, int connid, char *etag) |
|
446 |
+{ |
|
447 |
+ _wk *web=(_wk *)paramweb; |
|
448 |
+ wk_client *client; |
|
449 |
+ if(web==NULL) |
|
450 |
+ return(-1); |
|
451 |
+ if((client=wk_clientget(web,connid))==NULL) |
|
452 |
+ return(-1); |
|
453 |
+ if(etag!=NULL) { |
|
454 |
+ strncpy(client->etag,etag,sizeof(client->etag)); |
|
455 |
+ client->etag[sizeof(client->etag)-1]='\0'; |
|
456 |
+ } else |
|
457 |
+ client->etag[0]='\0'; |
|
458 |
+ return(0); |
|
459 |
+} |
|
441 | 460 |
|
442 | 461 |
int |
443 | 462 |
wk_serve_buffer_as_file(wk *paramweb, int connid, void *data, int datalen, const char *mime) |
... | ... |
@@ -447,28 +466,44 @@ wk_serve_buffer_as_file(wk *paramweb, int connid, void *data, int datalen, const |
447 | 466 |
wk_client *client; |
448 | 467 |
char buf[256]; |
449 | 468 |
sbuf *cookiebuf; |
469 |
+ int cachedetag; |
|
450 | 470 |
if(web==NULL) |
451 | 471 |
return(-1); |
452 | 472 |
if((client=wk_clientget(web,connid))==NULL) |
453 | 473 |
return(-1); |
454 |
- wk_writestr((wk *)web,connid,"HTTP/1.0 200 OK\r\n"); |
|
474 |
+ cachedetag=(wk_etagnotmodified(web,client)==0)?1:0; |
|
475 |
+ if(!cachedetag) |
|
476 |
+ wk_writestr((wk *)web,connid,"HTTP/1.0 200 OK\r\n"); |
|
477 |
+ else |
|
478 |
+ wk_writestr((wk *)web,connid,"HTTP/1.1 304 Not modified\r\n"); |
|
455 | 479 |
if(client->cookiebufid!=-1 && (cookiebuf=wk_sbufget((wk *)web,client->cookiebufid))!=NULL) { |
456 | 480 |
if(wk_write((wk *)web,connid,sbuf_getbytes(cookiebuf,sbuf_count(cookiebuf)),sbuf_count(cookiebuf))==-1 || |
457 | 481 |
sbuf_count(cookiebuf)!=0) |
458 | 482 |
return(-1); /* insufficient memory */ |
459 | 483 |
wk_sbufrelease((wk *)web,client->cookiebufid),client->cookiebufid=-1; |
460 | 484 |
} |
461 |
- sprintf(buf,"Content-Length: %i\r\n",datalen); |
|
462 |
- wk_writestr((wk *)web,connid,buf); |
|
463 |
- if(mime!=NULL && strlen(mime)<(sizeof(buf)-sizeof(strcontenttype)-3)) |
|
464 |
- sprintf(buf,"%s%s\r\n",strcontenttype,mime); |
|
465 |
- else |
|
466 |
- sprintf(buf,"%s%s\r\n",strcontenttype,"application/octet-stream"); |
|
467 |
- wk_writestr((wk *)web,connid,buf); |
|
485 |
+ if(!cachedetag) { |
|
486 |
+ if(client->etag[0]!='\0') { |
|
487 |
+ sprintf(buf,"ETag: \"%s\"\r\n",client->etag); |
|
488 |
+ client->etag[0]='\0'; |
|
489 |
+ wk_writestr((wk *)web,connid,buf); |
|
490 |
+ } |
|
491 |
+ sprintf(buf,"Content-Length: %i\r\n",datalen); |
|
492 |
+ wk_writestr((wk *)web,connid,buf); |
|
493 |
+ if(mime!=NULL && strlen(mime)<(sizeof(buf)-sizeof(strcontenttype)-3)) |
|
494 |
+ sprintf(buf,"%s%s\r\n",strcontenttype,mime); |
|
495 |
+ else |
|
496 |
+ sprintf(buf,"%s%s\r\n",strcontenttype,"application/octet-stream"); |
|
497 |
+ wk_writestr((wk *)web,connid,buf); |
|
498 |
+ } else { |
|
499 |
+ wk_writestr((wk *)web,connid,"Content-Length: 0\r\n"); |
|
500 |
+ } |
|
468 | 501 |
if(client->keepalive) |
469 | 502 |
wk_writestr((wk *)web,connid,"Connection: keep-alive\r\n"); |
470 | 503 |
wk_writestr((wk *)web,connid,"\r\n"); |
471 |
- return(wk_write((wk *)web,connid,data,datalen)); |
|
504 |
+ if(!cachedetag) |
|
505 |
+ return(wk_write((wk *)web,connid,data,datalen)); |
|
506 |
+ return(0); |
|
472 | 507 |
} |
473 | 508 |
|
474 | 509 |
int |
... | ... |
@@ -480,33 +515,47 @@ wk_serve_file(wk *paramweb, int connid, char *filename, const char *mime) |
480 | 515 |
char buf[256]; |
481 | 516 |
sbuf *cookiebuf; |
482 | 517 |
struct stat st; |
518 |
+ int cachedetag; |
|
483 | 519 |
if(web==NULL || filename==NULL) |
484 | 520 |
return(-1); |
485 | 521 |
if((client=wk_clientget(web,connid))==NULL) |
486 | 522 |
return(-1); |
487 | 523 |
if(client->fdtoserve!=-1) |
488 | 524 |
close(client->fdtoserve),client->fdtoserve=-1; |
489 |
- if((client->fdtoserve=open(filename,O_RDONLY))==-1) { |
|
490 |
- wk_serve_error((wk *)web,connid,wkerr_notfound); |
|
491 |
- return(-1); |
|
492 |
- } |
|
493 |
- wk_writestr((wk *)web,connid,"HTTP/1.1 200 OK\r\n"); |
|
525 |
+ cachedetag=(wk_etagnotmodified(web,client)==0)?1:0; |
|
526 |
+ if(!cachedetag) { |
|
527 |
+ if((client->fdtoserve=open(filename,O_RDONLY))==-1) { |
|
528 |
+ wk_serve_error((wk *)web,connid,wkerr_notfound); |
|
529 |
+ return(-1); |
|
530 |
+ } |
|
531 |
+ wk_writestr((wk *)web,connid,"HTTP/1.0 200 OK\r\n"); |
|
532 |
+ } else |
|
533 |
+ wk_writestr((wk *)web,connid,"HTTP/1.1 304 Not modified\r\n"); |
|
494 | 534 |
if(client->cookiebufid!=-1 && (cookiebuf=wk_sbufget((wk *)web,client->cookiebufid))!=NULL) { |
495 | 535 |
if(wk_write((wk *)web,connid,sbuf_getbytes(cookiebuf,sbuf_count(cookiebuf)),sbuf_count(cookiebuf))==-1 || |
496 | 536 |
sbuf_count(cookiebuf)!=0) |
497 | 537 |
return(-1); /* insufficient memory */ |
498 | 538 |
wk_sbufrelease((wk *)web,client->cookiebufid),client->cookiebufid=-1; |
499 | 539 |
} |
500 |
- if(fstat(client->fdtoserve,&st)==0) { |
|
501 |
- sprintf(buf,"Content-Length: %lld\r\n",(long long)st.st_size); |
|
540 |
+ if(!cachedetag) { |
|
541 |
+ if(client->etag[0]!='\0') { |
|
542 |
+ sprintf(buf,"ETag: \"%s\"\r\n",client->etag); |
|
543 |
+ client->etag[0]='\0'; |
|
544 |
+ wk_writestr((wk *)web,connid,buf); |
|
545 |
+ } |
|
546 |
+ if(fstat(client->fdtoserve,&st)==0) { |
|
547 |
+ sprintf(buf,"Content-Length: %lld\r\n",(long long)st.st_size); |
|
548 |
+ wk_writestr((wk *)web,connid,buf); |
|
549 |
+ } else |
|
550 |
+ client->keepalive=0; |
|
551 |
+ if(mime!=NULL && strlen(mime)<(sizeof(buf)-sizeof(strcontenttype)-3)) |
|
552 |
+ sprintf(buf,"%s%s\r\n",strcontenttype,mime); |
|
553 |
+ else |
|
554 |
+ sprintf(buf,"%s%s\r\n",strcontenttype,"application/octet-stream"); |
|
502 | 555 |
wk_writestr((wk *)web,connid,buf); |
503 |
- } else |
|
504 |
- client->keepalive=0; |
|
505 |
- if(mime!=NULL && strlen(mime)<(sizeof(buf)-sizeof(strcontenttype)-3)) |
|
506 |
- sprintf(buf,"%s%s\r\n",strcontenttype,mime); |
|
507 |
- else |
|
508 |
- sprintf(buf,"%s%s\r\n",strcontenttype,"application/octet-stream"); |
|
509 |
- wk_writestr((wk *)web,connid,buf); |
|
556 |
+ } else { |
|
557 |
+ wk_writestr((wk *)web,connid,"Content-Length: 0\r\n"); |
|
558 |
+ } |
|
510 | 559 |
if(client->keepalive) |
511 | 560 |
wk_writestr((wk *)web,connid,"Connection: keep-alive\r\n"); |
512 | 561 |
wk_writestr((wk *)web,connid,"\r\n"); |
... | ... |
@@ -1051,6 +1100,7 @@ wk_clientacquire(_wk *web) |
1051 | 1100 |
client->fdtoserve=-1; |
1052 | 1101 |
client->headerbufid=-1; |
1053 | 1102 |
client->cookiebufid=-1; |
1103 |
+ client->etag[0]='\0'; |
|
1054 | 1104 |
return(client); |
1055 | 1105 |
} |
1056 | 1106 |
|
... | ... |
@@ -1225,6 +1275,9 @@ wk_clientservicereadheader(_wk *web, wk_client *client) |
1225 | 1275 |
client->uriready=1; |
1226 | 1276 |
client->continuationactive=0; |
1227 | 1277 |
client->status=wkc_header; |
1278 |
+ if(client->cookiebufid!=-1) |
|
1279 |
+ wk_sbufrelease((wk *)web,client->cookiebufid),client->cookiebufid=-1; |
|
1280 |
+ client->etag[0]='\0'; |
|
1228 | 1281 |
} |
1229 | 1282 |
return(0); |
1230 | 1283 |
} |
... | ... |
@@ -1431,4 +1484,21 @@ wk_postfree(_wk *web, wk_client *client) |
1431 | 1484 |
return(0); |
1432 | 1485 |
} |
1433 | 1486 |
|
1487 |
+static int |
|
1488 |
+wk_etagnotmodified(_wk *web, wk_client *client) |
|
1489 |
+{ |
|
1490 |
+ char *h; |
|
1491 |
+ int len; |
|
1492 |
+ int etaglen; |
|
1493 |
+ if(client->etag[0]=='\0') |
|
1494 |
+ return(-1); |
|
1495 |
+ if((h=wk_uri_getheader(&(client->uri),"If-None-Match",NULL))==NULL) |
|
1496 |
+ return(-1); |
|
1497 |
+ etaglen=strlen(client->etag); |
|
1498 |
+ if((len=strlen(h))<2 || h[0]!='\"' || h[len-1]!='\"') |
|
1499 |
+ return(-1); |
|
1500 |
+ if((len-2)!=etaglen || memcmp(h+1,client->etag,etaglen)!=0) |
|
1501 |
+ return(-1); |
|
1502 |
+ return(0); |
|
1503 |
+} |
|
1434 | 1504 |
|
... | ... |
@@ -52,6 +52,7 @@ wk_uri *wk_geturi(wk *web, int connid); /* for use in callback_event() when wke_ |
52 | 52 |
int wk_service(wk *web); /* To be called after sselelect_wait() but before sselect_getXXX() */ |
53 | 53 |
|
54 | 54 |
int wk_serve_cookieadd(wk *web, int connid, char *cookiename, char *value, char *domain, int maxage, char *attributes); |
55 |
+int wk_serve_etagset(wk *web, int connid, char *etag); |
|
55 | 56 |
int wk_serve_buffer_as_file(wk *web, int connid, void *data, int datalen, const char *mime); |
56 | 57 |
int wk_serve_file(wk *web, int connid, char *filename, const char *mime); |
57 | 58 |
int wk_serve_error(wk *web, int connid, wk_error wkerror); |