{"id":40,"date":"2006-04-10T22:54:25","date_gmt":"2006-04-10T20:54:25","guid":{"rendered":"http:\/\/kpumuk.info\/php\/correct-last-modified-header-processing\/"},"modified":"2015-09-08T01:42:07","modified_gmt":"2015-09-07T23:42:07","slug":"correct-last-modified-header-processing","status":"publish","type":"post","link":"https:\/\/kpumuk.info\/php\/correct-last-modified-header-processing\/","title":{"rendered":"Correct Last-Modified header processing"},"content":{"rendered":"<p>This is quick post about <tt>Last-Modified<\/tt> header. Please imagine following situation: you have image stored in your database and you need to send it to the browser on some request. But image extraction from database takes some time, and if there are more than one image you Web-server&#8217;s productivity will decrease dramatically. Is this case you need to implement caching functionality in your application. All images can be changed therefor you need to have ability to check image modified date (for example, this date can be stored in same database).<\/p>\n<p><!--more--><\/p>\n<p>Every browser has its own cache, and if you will send right <tt>Cache-Control<\/tt> header, your image will be cached for some time. After cache time expiring browser will send request to your application to get fresh version of image. But if your image was not updated you can send <tt>304<\/tt> code in response to tell browser about this. Look at the following code snippet:<\/p>\n<div class=\"codecolorer-container php twitlight\" style=\"overflow:auto;white-space:nowrap;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>1<br \/>2<br \/>3<br \/>4<br \/>5<br \/>6<br \/>7<br \/>8<br \/>9<br \/>10<br \/>11<br \/>12<br \/>13<br \/>14<br \/>15<br \/>16<br \/>17<br \/>18<br \/>19<br \/>20<br \/>21<br \/>22<br \/>23<br \/>24<br \/>25<br \/>26<br \/><\/div><\/td><td><div class=\"php codecolorer\"><span class=\"co1\">\/\/ --- Your code ---<\/span><br \/>\n<br \/>\n<span class=\"co1\">\/\/ You need past following before any output<\/span><br \/>\n<br \/>\n<span class=\"co1\">\/\/ here you need to select modified date from DB in UNIX timestamp format<\/span><br \/>\n<span class=\"co1\">\/\/ (same as time() function in PHP or UNIX_TIMESTAMP() function in MySQL)<\/span><br \/>\n<span class=\"re0\">$date<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw3\">time<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n<span class=\"re0\">$last_modified<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw3\">gmdate<\/span><span class=\"br0\">&#40;<\/span><span class=\"st_h\">'D, d M Y H:i:s'<\/span><span class=\"sy0\">,<\/span> <span class=\"re0\">$date<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">.<\/span> <span class=\"st_h\">' GMT'<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"co1\">\/\/ did the browser send an if-modified-since request?<\/span><br \/>\n<span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"kw3\">isset<\/span><span class=\"br0\">&#40;<\/span><span class=\"re0\">$_SERVER<\/span><span class=\"br0\">&#91;<\/span><span class=\"st_h\">'HTTP_IF_MODIFIED_SINCE'<\/span><span class=\"br0\">&#93;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; <span class=\"co1\">\/\/ parse header<\/span><br \/>\n&nbsp; <span class=\"re0\">$if_modified_since<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw3\">preg_replace<\/span><span class=\"br0\">&#40;<\/span><span class=\"st_h\">'\/;.*$\/'<\/span><span class=\"sy0\">,<\/span> <span class=\"st_h\">''<\/span><span class=\"sy0\">,<\/span> <span class=\"re0\">$_SERVER<\/span><span class=\"br0\">&#91;<\/span><span class=\"st_h\">'HTTP_IF_MODIFIED_SINCE'<\/span><span class=\"br0\">&#93;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"re0\">$if_modified_since<\/span> <span class=\"sy0\">==<\/span> <span class=\"re0\">$last_modified<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"co1\">\/\/ the browser's cache is still up to date<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw3\">header<\/span><span class=\"br0\">&#40;<\/span><span class=\"st_h\">'HTTP\/1.0 304 Not Modified'<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw3\">header<\/span><span class=\"br0\">&#40;<\/span><span class=\"st_h\">'Cache-Control: max-age=86400, must-revalidate'<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw3\">exit<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n<span class=\"kw3\">header<\/span><span class=\"br0\">&#40;<\/span><span class=\"st_h\">'Cache-Control: max-age=86400, must-revalidate'<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw3\">header<\/span><span class=\"br0\">&#40;<\/span><span class=\"st_h\">'Last-Modified: '<\/span> <span class=\"sy0\">.<\/span> <span class=\"re0\">$last_modified<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n<span class=\"co1\">\/\/ --- Your code ---<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n<p>In this code I check <tt>HTTP_IF_MODIFIED_SINCE<\/tt> request variable which will be sent by browser when cache is expired. If image was not modified, special header will be sent. Default cache period in this sample is 24 hours (86400 seconds). This is very simple and powerful issue which can be used in your Web-application as-is to increase perfomance.<\/p>\n<p>Hint: you can create static-like URLs using following lines in <tt>.htaccess<\/tt> file (mod_rewrite):<\/p>\n<div class=\"codecolorer-container text twitlight\" style=\"overflow:auto;white-space:nowrap;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>1<br \/>2<br \/><\/div><\/td><td><div class=\"text codecolorer\">RewriteEngine On<br \/>\nRewriteRule ^image_([0-9]+).php$ getimage.php?image=$1 [L]<\/div><\/td><\/tr><\/tbody><\/table><\/div>\n<p>In this case your images will have URLs like <tt>http:\/\/example.com\/image_10.php<\/tt>, and all request will be redirected to <tt>getimage.php<\/tt> with parameter <tt>image=10<\/tt>.<\/p>\n<h2>Useful links<\/h2>\n<ul>\n<li><a href=\"http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec10.html\" target=\"_blank\">HTTP\/1.1: Status Code Definitions<\/a><\/li>\n<li><a href=\"http:\/\/www.w3.org\/Protocols\/rfc2616\/rfc2616-sec14.html\" target=\"_blank\">HTTP\/1.1: Header Field Definitions<\/a><\/li>\n<li><a href=\"http:\/\/www.amazon.com\/exec\/obidos\/redirect?link_code=as2&#038;path=ASIN\/156592536X&#038;tag=dmytroshtefly-20&#038;camp=1789&#038;creative=9325\">Web Caching (O&#8217;Reilly Internet Series)<\/a><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.assoc-amazon.com\/e\/ir?t=dmytroshtefly-20&#038;l=as2&#038;o=1&#038;a=156592536X\" width=\"1\" height=\"1\" border=\"0\" alt=\"\" style=\"border:none !important; margin:0px !important;\" \/><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>This is quick post about Last-Modified header. Please imagine following situation: you have image stored in your database and you need to send it to the browser on some request. But image extraction from database takes some time, and if there are more than one image you Web-server&#8217;s productivity will decrease dramatically. Is this case [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[219],"tags":[109,108,107,110,9],"class_list":["post-40","post","type-post","status-publish","format-standard","hentry","category-php","tag-caching","tag-headers","tag-http","tag-last-modified","tag-php"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/kpumuk.info\/wp-json\/wp\/v2\/posts\/40","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kpumuk.info\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kpumuk.info\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kpumuk.info\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kpumuk.info\/wp-json\/wp\/v2\/comments?post=40"}],"version-history":[{"count":4,"href":"https:\/\/kpumuk.info\/wp-json\/wp\/v2\/posts\/40\/revisions"}],"predecessor-version":[{"id":1307,"href":"https:\/\/kpumuk.info\/wp-json\/wp\/v2\/posts\/40\/revisions\/1307"}],"wp:attachment":[{"href":"https:\/\/kpumuk.info\/wp-json\/wp\/v2\/media?parent=40"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kpumuk.info\/wp-json\/wp\/v2\/categories?post=40"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kpumuk.info\/wp-json\/wp\/v2\/tags?post=40"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}