Browse code

add etags for in-memory pages and for the banner (IOW, etags not implemented for XHR replies)

Dario Rodriguez authored on 16/07/2014 13:32:00
Showing 1 changed files
... ...
@@ -15,6 +15,7 @@
15 15
 #include <sys/types.h>
16 16
 #include <sys/stat.h>
17 17
 #include <unistd.h>
18
+#include <mhash.h>
18 19
 #include "gen_res.h"
19 20
 #include "socklib.h"
20 21
 #include "loglib.h"
... ...
@@ -32,12 +33,15 @@
32 33
 #define CFBANNERPATH "default.png"
33 34
 #define CFSSLPROXY 0
34 35
 
36
+#define DEBUG_HEADERS
37
+
35 38
 static int signal_init(int signum, void (*fn)(int));
36 39
 static void sigint(int signum);
37 40
 volatile int sigint_flag=0;
38 41
 
39 42
 int kakumei_inviteexists(kakumei *ka, char *invite);
40 43
 int kakumei_invitedel(kakumei *ka, char *invite);
44
+int kakumei_etag(kakumei *ka, char *filename, char *etag, int etagsize);
41 45
 
42 46
 wk_action callback_http(wk *web, int connid, wk_uri *uri, void *userptr);
43 47
 wk_action http_login(wk *web, int connid, wk_uri *uri, void *userptr);
... ...
@@ -177,6 +181,38 @@ kakumei_invitedel(kakumei *ka, char *invite)
177 181
         return(0);
178 182
 }
179 183
 
184
+int
185
+kakumei_etag(kakumei *ka, char *filename, char *etag, int etagsize)
186
+{
187
+        struct stat st;
188
+        MHASH td;
189
+        char binhash[20];
190
+        char hash[40];
191
+        int i;
192
+        char c;
193
+        if(filename==NULL || etag==NULL || etagsize<1)
194
+                return(-1);
195
+        if(stat(filename,&st)!=0 || !S_ISREG(st.st_mode))
196
+                return(-1);
197
+        if((td=mhash_init(MHASH_SHA1))==MHASH_FAILED)
198
+                return(-1);
199
+        mhash(td,&(st.st_mtime),sizeof(st.st_mtime));
200
+        mhash(td,&(st.st_size),sizeof(st.st_size));
201
+        mhash_deinit(td,&binhash);
202
+        for(i=0;i<sizeof(binhash);i++) {
203
+                c=(((unsigned char *)binhash)[i]>>4);
204
+                c=(c>=10)?(c-10+'a'):c+'0';
205
+                hash[i<<1]=c;
206
+                c=(((unsigned char *)binhash)[i]&0xf);
207
+                c=(c>=10)?(c-10+'a'):c+'0';
208
+                hash[(i<<1)+1]=c;
209
+        }
210
+        memcpy(etag,hash,(etagsize>sizeof(hash))?sizeof(hash):(etagsize-1));
211
+        etag[(etagsize>sizeof(hash))?sizeof(hash):(etagsize-1)]='\0';
212
+        return(0);
213
+}
214
+
215
+
180 216
 
181 217
 wk_action
182 218
 callback_http(wk *web, int connid, wk_uri *uri, void *userptr)
... ...
@@ -185,6 +221,7 @@ callback_http(wk *web, int connid, wk_uri *uri, void *userptr)
185 221
         resindex *res;
186 222
         char partialpath[1024];
187 223
         char *ptr;
224
+        char etag[ETAGSIZE+1];
188 225
         struct {
189 226
                 char *name;
190 227
         } whitelist[]={{"/index.html"},
... ...
@@ -207,6 +244,14 @@ callback_http(wk *web, int connid, wk_uri *uri, void *userptr)
207 244
                 log_write("HTTP","Request: /newuser?...");
208 245
         else
209 246
                 log_write("HTTP","Request: %s",uri->path);
247
+#ifdef DEBUG_HEADERS
248
+        {
249
+                int j;
250
+                char *h;
251
+                for(j=0;(h=wk_uri_getheaderbynum(uri,j))!=NULL;j++)
252
+                        log_write("HDR","%s",h);
253
+        }
254
+#endif
210 255
         /* extract the name */
211 256
         strncpy(partialpath,uri->path,sizeof(partialpath)-1);
212 257
         partialpath[sizeof(partialpath)-1]='\0';
... ...
@@ -238,6 +283,7 @@ callback_http(wk *web, int connid, wk_uri *uri, void *userptr)
238 283
         if(partialpath[0]=='/' && (res=res_find(resindexdata,partialpath+1))!=NULL) {
239 284
                 if(whitelisted || validsession) {
240 285
                         log_write("HTTP","Serving in-memory file %s",partialpath+1);
286
+                        wk_serve_etagset(web,connid,res->etag);
241 287
                         wk_serve_buffer_as_file(web,connid,res->data,res->len,mime_getdefault(res->name,"application/octet-stream"));
242 288
                         return(wkact_finished);
243 289
                 } else if((res=res_find(resindexdata,"index.html"))!=NULL) {
... ...
@@ -251,6 +297,8 @@ callback_http(wk *web, int connid, wk_uri *uri, void *userptr)
251 297
                 }
252 298
         } else if(strcmp(uri->path,"/banner.png")==0) {
253 299
                 log_write("HTTP","Serving banner from disk, file %s",partialpath);
300
+                if(kakumei_etag(ka,partialpath,etag,sizeof(etag))==0)
301
+                        wk_serve_etagset(web,connid,etag);
254 302
                 if(wk_serve_file(web,connid,partialpath,mime_getdefault(partialpath,"image/png"))!=0) {
255 303
                         log_write("HTTP","File not found, file %s",partialpath);
256 304
                         wk_serve_error(web,connid,wkerr_notfound);