diff options
author | Clayton <nrootconauto@gmail.com> | 2023-02-28 20:09:07 -0500 |
---|---|---|
committer | Clayton <nrootconauto@gmail.com> | 2023-02-28 20:09:07 -0500 |
commit | 7faa4e295525624b331a3b838b256a2d2d7bbca2 (patch) | |
tree | e863546c3f9abce9b101ad274c53404918016400 | |
parent | 83fbfa6b6ebc84b3a604c80a4269bb32e2edd5d3 (diff) |
Added HTTP cache mechanism
Uses ETags to track the file cache
-rw-r--r-- | T/Server/backup.HC | 2 | ||||
-rw-r--r-- | T/Server/etags.HC | 41 | ||||
-rw-r--r-- | T/Server/gen_html.HC | 3 | ||||
-rw-r--r-- | T/Server/http.HC | 46 | ||||
-rw-r--r-- | T/Server/run.HC | 5 |
5 files changed, 87 insertions, 10 deletions
diff --git a/T/Server/backup.HC b/T/Server/backup.HC index d7911d1..563134f 100644 --- a/T/Server/backup.HC +++ b/T/Server/backup.HC @@ -67,7 +67,7 @@ ent: } timestamp=MStrPrint(WIKI_BACKUP_HEADER,t1,clone,user,Now,Now); Free(t1); - timestamp2=MStrPrint("%D_%T",time,time); + timestamp2=MStrPrint("%D_%T",time,time); while(StrFirstOcc(timestamp2,"/")) *StrFirstOcc(timestamp2,"/")='-'; while(StrFirstOcc(timestamp2,":")) diff --git a/T/Server/etags.HC b/T/Server/etags.HC new file mode 100644 index 0000000..0b1582a --- /dev/null +++ b/T/Server/etags.HC @@ -0,0 +1,41 @@ +U8 *RegisterETag(CServer *srv,U8 *file) { + CDirEntry dent; + CHashGeneric *gen; + U8 *tmp,*h; + file=ChrootFile(file); + if(FileFind(file,&dent)) { + gen=CAlloc(sizeof(CHashGeneric)+StrLen(file)+1,srv->task); + gen->type=HTT_FRAME_PTR; + tmp=MStrPrint("%s@%D@%T",file,dent.datetime,dent.datetime); + h=FNV64Str(tmp); + gen->str=StrNew(h,srv->task); + StrCpy(gen+1,file); + gen->user_data0=dent.datetime; + gen->user_data1=gen+1; + HashAdd(gen,srv->task->hash_table); + Free(h); + Free(tmp); + Free(dent.full_name); + tmp=MStrPrint("%s",gen->str); + } else + tmp=NULL; + Free(file); + return tmp; +} +Bool ETagChanged(CServer *srv,U8 *etag) { + CHashGeneric *gen=HashFind(etag,srv->task->hash_table,HTT_FRAME_PTR); + CDirEntry dent; + Bool ret=TRUE; + if(gen) { + if(!FileFind(gen->user_data1,&dent)) { + ret=TRUE; + goto fin; + } + Free(dent.full_name); + ret=dent.datetime>gen->user_data0; + } +fin: + if(gen&&ret) + HashRemDel(gen,srv->task->hash_table); + return ret; +}
\ No newline at end of file diff --git a/T/Server/gen_html.HC b/T/Server/gen_html.HC index d8fccdc..6581928 100644 --- a/T/Server/gen_html.HC +++ b/T/Server/gen_html.HC @@ -21,6 +21,7 @@ U0 FileGet(CServer *srv,CDyadStream*stream,CURL *url,CHTTPRequest *req) { StrCpy(con->response_mime,mime); con->response_code=200; WriteNBytes(stream,NULL,f,len); + con->cache_age=24*60*60*3; //3Days lol Free(f); } else { R404(stream,&len,url->abs_path); @@ -588,4 +589,4 @@ fin: CServer *srv=CreateServer(8080); srv->get=&Get; srv->post=&Post; -Serve(srv);
\ No newline at end of file +Serve(srv); diff --git a/T/Server/http.HC b/T/Server/http.HC index a04236f..df6baa9 100644 --- a/T/Server/http.HC +++ b/T/Server/http.HC @@ -28,7 +28,8 @@ class CConnection:CQue { CUniqueToken *unique_token; I64 is_dead,lock,response_length; U8 *session_cookie,*response_text; - I64 response_code,cache_age; + I64 response_code,cache_age; + Bool etag_changed,provided_etag; U8 response_mime[STR_LEN]; U8 boundary[STR_LEN]; U8 field[STR_LEN]; @@ -254,12 +255,18 @@ CConnection *connects=MAlloc(sizeof(CQue)); QueInit(connects); I64 con_locked=0; U0 SendRequest(CDyadStream *s) { - U8 *tmp,*cookie; + U8 *tmp,*tmp2,*cookie; U8 *msg="200 OK"; CConnection *con=Fs->user_data; + if(con->provided_etag&&!con->etag_changed) + con->response_code=304; switch(con->response_code) { break;case 200: msg="200 OK"; - break;case 404: msg="404 NOT FOUND"; + break;case 404: msg="404 Not Found"; + break;case 304: msg="304 Not Modified"; +//If we have a 304(not-modefied) +//We will ommit the body + con->response_length=0; } tmp=MStrPrint( "HTTP/1.1 %s\x0d\n" @@ -269,6 +276,19 @@ U0 SendRequest(CDyadStream *s) { ); DyadWrite(s,tmp,StrLen(tmp)); Free(tmp); + if(con->cache_age) { + tmp2=RegisterETag(con->server,con->url->abs_path); + if(tmp2) { + tmp=MStrPrint( + "Date: %D\x0d\n" + "Cache-Control: max-age=%d\x0d\n" + "ETag: \"%q\"\x0d\n" + ,Now,con->cache_age,tmp2); + DyadWrite(s,tmp,StrLen(tmp)); + Free(tmp); + } + Free(tmp2); + } if(cookie=FramePtr(WIKI_SESSION_COOKIE)) { tmp="Credentials: include\x0d\n" "Mode: cors\x0d\n" @@ -365,7 +385,7 @@ U0 SReadLine(CDyadStream *s,U8 *data,I64 len,CUniqueToken *ut) { Yield; CConnection *first,*con,*con2; CHashGeneric *hash; - U8 *buf=MAlloc(len+1),*buf2=MAlloc(len+1); + U8 *buf,*buf2; U8 *fb,*http2,*t1,*t2,*odata; first=connects; for(con=first->next;con!=first;con=con->next) { @@ -382,6 +402,7 @@ U0 SReadLine(CDyadStream *s,U8 *data,I64 len,CUniqueToken *ut) { con->name=StrNew("",con->hc); con->post_data=HashTableNew(0x10,con->hc); found: + buf=MAlloc(len+1,con->hc),buf2=MAlloc(len+1,con->hc); while(LBts(&con->lock,0)) Yield; if(len==2) con->state.u8[0]=CON_S_BLANK_LINE; @@ -441,7 +462,21 @@ qloop: } } } - if(!Bt(&con->state,CONf_DATA)&&!StrNCmp(data,"Connection",StrLen("Connection"))) { + if(!Bt(&con->state,CONf_DATA)&&!StrNICmp(data,"If-None-Match",StrLen("If-None-Match"))) { + con->provided_etag=TRUE; + data=SkipWhitespace(StrFirstOcc(data,":")+1); +etag_loop: + t1=buf; + data=StrScan(data,"\"%s\"",&t1); + if(ETagChanged(con->server,buf)){ + TOSPrint("ETAG_CHANGED:%s\n",buf); + con->etag_changed=1; + } + if(*data==',') { + data=SkipWhitespace(data+1); + goto etag_loop; + } + } else if(!Bt(&con->state,CONf_DATA)&&!StrNCmp(data,"Connection",StrLen("Connection"))) { data=SkipWhitespace(StrFirstOcc(data,":")+1); BEqu(&con->state,CONf_KEEP_ALIVE,ToBool(StrIMatch("keep-alive",data))); } else if(!Bt(&con->state,CONf_DATA)&&!StrNCmp(data,"Cookie",StrLen("Cookie"))) { @@ -604,7 +639,6 @@ found: U0 ListenCallback(CDyadStream *s,CServer *srv) { CUniqueToken *ut=MAlloc(sizeof(CUniqueToken)); ut->srv=srv; - DyadSetTimeout(s,1); DyadSetReadCallback(s,&SReadLine,ut); DyadSetOnCloseCallback(s,&CloseCallback,ut); } diff --git a/T/Server/run.HC b/T/Server/run.HC index 4b36970..0a61834 100644 --- a/T/Server/run.HC +++ b/T/Server/run.HC @@ -27,7 +27,7 @@ extern U0 FinalizeHTTPHeader(CDyadStream*); extern U8 *GetCurrentUserName(); extern U8 *GetCurrentUser(); extern Bool CurrentUserIsBanned(); -//Checks if not logged in too +//Checks if not logged in too extern Bool UserPrivCheck(CServer *srv,CDyadStream *stream,CURL *url,CHTTPRequest *req,U8 *file); extern Bool FileIsSalted(U8 *file); extern Bool CurrentUserIsAdmin(); @@ -62,8 +62,10 @@ if(!FileFind(WIKI_PREVIEW)) DirMk(WIKI_PREVIEW); if(!FileFind(WIKI_BACKUP)) DirMk(WIKI_BACKUP); +#include "AUTH.HC" #include "DynamStr.HC" #include "utils.HC" +#include "etags.HC" #include "http.HC" #include "header_footer.HC" #include "find.HC" @@ -74,6 +76,5 @@ if(!FileFind(WIKI_BACKUP)) #include "edit.HC" #include "index.HC" #include "cache.HC" -#include "AUTH.HC" #include "users.HC" #include "gen_html.HC";
\ No newline at end of file |