Ignore:
Timestamp:
05/10/11 00:30:39 (9 years ago)
Author:
Admin
Message:

WebIf: Further improve browser caching through implementation of etag/if-none-match header for images/css/js

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/oscam-http-helpers.c

    r5212 r5213  
    353353                    if(str[2] == '-' && str[6] == '-'){
    354354                        day = atoi(str);
    355                         year = atoi(str + 6) + 2000;
     355                        year = atoi(str + 7) + 2000;
    356356                    }
    357357                    break;
     
    469469}
    470470
    471 void send_headers(FILE *f, int32_t status, char *title, char *extra, char *mime, int32_t cache, int32_t length, int8_t forcePlain){
     471
     472void send_headers(FILE *f, int32_t status, char *title, char *extra, char *mime, int32_t cache, int32_t length, char *content, int8_t forcePlain){
    472473  time_t now;
    473474  char timebuf[32];
    474   char buf[sizeof(PROTOCOL) + sizeof(SERVER) + strlen(title) + (extra == NULL?0:strlen(extra)+2) + (mime == NULL?0:strlen(mime)+2) + 300];
     475  char buf[sizeof(PROTOCOL) + sizeof(SERVER) + strlen(title) + (extra == NULL?0:strlen(extra)+2) + (mime == NULL?0:strlen(mime)+2) + 350];
    475476  char *pos = buf;
    476477   
     
    488489        pos += snprintf(pos, sizeof(buf)-(pos-buf),"Content-Type: %s\r\n", mime);
    489490
    490     if(!cache){
    491         pos += snprintf(pos, sizeof(buf)-(pos-buf),"Cache-Control: no-store, no-cache, must-revalidate\r\n");
    492         pos += snprintf(pos, sizeof(buf)-(pos-buf),"Expires: Sat, 10 Jan 2000 05:00:00 GMT\r\n");
    493     } else {
    494         pos += snprintf(pos, sizeof(buf)-(pos-buf),"Cache-Control: public, max-age=7200\r\n");
    495     }
    496     pos += snprintf(pos, sizeof(buf)-(pos-buf),"Content-Length: %d\r\n", length);
    497     if(status != 304) pos += snprintf(pos, sizeof(buf)-(pos-buf),"Last-Modified: %s\r\n", timebuf);
     491    if(status != 304){
     492        if(!cache){
     493            pos += snprintf(pos, sizeof(buf)-(pos-buf),"Cache-Control: no-store, no-cache, must-revalidate\r\n");
     494            pos += snprintf(pos, sizeof(buf)-(pos-buf),"Expires: Sat, 10 Jan 2000 05:00:00 GMT\r\n");
     495        } else {
     496            pos += snprintf(pos, sizeof(buf)-(pos-buf),"Cache-Control: public, max-age=7200\r\n");
     497        }
     498        pos += snprintf(pos, sizeof(buf)-(pos-buf),"Content-Length: %d\r\n", length);
     499        pos += snprintf(pos, sizeof(buf)-(pos-buf),"Last-Modified: %s\r\n", timebuf);
     500        if(content){
     501            pos += snprintf(pos, sizeof(buf)-(pos-buf),"ETag: \"%u\"\r\n", (uint32_t)crc32(0L, (uchar *)content, strlen(content)));
     502        }
     503    }
    498504    pos += snprintf(pos, sizeof(buf)-(pos-buf), "Connection: close\r\n");
    499505    pos += snprintf(pos, sizeof(buf)-(pos-buf),"\r\n");
     
    502508}
    503509
     510
     511void send_error(FILE *f, int32_t status, char *title, char *extra, char *text, int8_t forcePlain){
     512    char buf[(2* strlen(title)) + strlen(text) + 128];
     513    char *pos = buf;
     514    send_headers(f, status, title, extra, "text/html", 0, strlen(buf), NULL, forcePlain);
     515    pos += snprintf(pos, sizeof(buf)-(pos-buf), "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\r\n", status, title);
     516    pos += snprintf(pos, sizeof(buf)-(pos-buf), "<BODY><H4>%d %s</H4>\r\n", status, title);
     517    pos += snprintf(pos, sizeof(buf)-(pos-buf), "%s\r\n", text);
     518    pos += snprintf(pos, sizeof(buf)-(pos-buf), "</BODY></HTML>\r\n");
     519    if(forcePlain == 1) fwrite(buf, 1, strlen(buf), f);
     520    else webif_write(buf, f);
     521}
     522
     523void send_error500(FILE *f){
     524    send_error(f, 500, "Internal Server Error", NULL, "The server encountered an internal error that prevented it from fulfilling this request.", 0);
     525}
     526
    504527/*
    505528 * function for sending files.
    506529 */
    507 void send_file(FILE *f, char *filename, time_t modifiedheader){
     530void send_file(FILE *f, char *filename, time_t modifiedheader, uint32_t etagheader){
    508531    int32_t fileno = 0;
    509     char* mimetype = "";
     532    char* mimetype = "", *result = "";
     533    time_t moddate;
    510534
    511535    if (!strcmp(filename, "CSS")){
     
    521545    if(strlen(filename) > 0 && file_exists(filename) == 1){
    522546        FILE *fp;
    523         char buffer[1024];
     547        char buffer[1024], *pos;
    524548        int32_t read;
    525549        struct stat st;
    526550       
    527551        stat(filename, &st);
    528         if(st.st_mtime < modifiedheader){
    529             send_headers(f, 304, "Not Modified", NULL, NULL, 1, 0, 0);
     552        moddate = st.st_mtime;
     553        if((fp = fopen(filename, "r"))==NULL) return;
     554        if(!cs_malloc(&result, st.st_size + 1, -1)){
     555            send_error500(f);
     556            fclose(fp);
    530557            return;
    531558        }
    532         if((fp = fopen(filename, "r"))==NULL) return;
    533         send_headers(f, 200, "OK", NULL, mimetype, 1, st.st_size, 0);
     559        result[0] = '\0';
     560        pos = result;
    534561        while((read = fread(buffer,sizeof(char), 1023, fp)) > 0) {
    535             buffer[read] = '\0';           
    536             webif_write(buffer, f);
    537         }
    538 
    539         fclose (fp);
     562            buffer[read] = '\0';
     563            if(pos + read > result + st.st_size) break;     //nasty, file has grown while reading   
     564            memcpy(&pos, buffer, read);
     565            pos += read;   
     566        }       
     567        fclose(fp);
    540568    } else {
    541         if((fileno == 1 || fileno == 2) && first_client->login < modifiedheader){
    542             send_headers(f, 304, "Not Modified", NULL, NULL, 1, 0, 0);
    543             return;
    544         }
     569        moddate = first_client->login;
    545570        if (fileno == 1){
    546             send_headers(f, 200, "OK", NULL, mimetype, 1, strlen(CSS), 0);
    547             webif_write(CSS, f);
     571            result = CSS;
    548572        } else if (fileno == 2){
    549             send_headers(f, 200, "OK", NULL, mimetype, 1, strlen(JSCRIPT), 0);
    550             webif_write(JSCRIPT, f);
    551         }
    552     }
    553 }
    554 
    555 void send_error(FILE *f, int32_t status, char *title, char *extra, char *text, int8_t forcePlain){
    556     char buf[(2* strlen(title)) + strlen(text) + 128];
    557     char *pos = buf;
    558     send_headers(f, status, title, extra, "text/html", 0, strlen(buf), forcePlain);
    559     pos += snprintf(pos, sizeof(buf)-(pos-buf), "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\r\n", status, title);
    560     pos += snprintf(pos, sizeof(buf)-(pos-buf), "<BODY><H4>%d %s</H4>\r\n", status, title);
    561     pos += snprintf(pos, sizeof(buf)-(pos-buf), "%s\r\n", text);
    562     pos += snprintf(pos, sizeof(buf)-(pos-buf), "</BODY></HTML>\r\n");
    563     if(forcePlain == 1) fwrite(buf, 1, strlen(buf), f);
    564     else webif_write(buf, f);
    565 }
    566 
    567 void send_error500(FILE *f){
    568     send_error(f, 500, "Internal Server Error", NULL, "The server encountered an internal error that prevented it from fulfilling this request.", 0);
     573            result = JSCRIPT;
     574        }
     575    }
     576    if(moddate < modifiedheader || (uint32_t)crc32(0L, (uchar *)result, strlen(result)) == etagheader){
     577        send_headers(f, 304, "Not Modified", NULL, NULL, 1, strlen(result), result, 0);
     578    } else {
     579        send_headers(f, 200, "OK", NULL, mimetype, 1, strlen(result), result, 0);
     580        webif_write(result, f);
     581    }
    569582}
    570583
Note: See TracChangeset for help on using the changeset viewer.