Название: Кеширование по размеру или контенту Отправлено: Terfe от 15 сентября 2016, 19:48:55 Есть сайт, у которого ссылки на файлы являются уникальными, никогда не повторяющимися. Ссылка в виде бессвязного набора символов (генерируется рандомно, видимо). Количество файлов весьма ограничено. Браузер и НС, естественно, закачивают каждый файл по ссылке при навигации по сайту.
Как можно закешировать файлы, чтоб они не скачивались каждый раз заново, хотя бы для конкретного сайта? Сайт отдает файлы в gzip. Внутри архивов одинаковые имена файлов. Если не НС, то может есть сторонние средства, которые позволят закешировать по размеру (хотя бы) или контенту? Название: Re: Кеширование по размеру или контенту Отправлено: Zork от 16 сентября 2016, 05:02:10 Что бы не обновлять файлы по размеру используйте расширение eA_Dont_update_file_by_size из дистрибутива HC
Название: Re: Кеширование по размеру или контенту Отправлено: Anymore от 16 сентября 2016, 08:08:24 Так то бы на сам сайт посмотреть.
Название: Re: Кеширование по размеру или контенту Отправлено: YuS от 16 сентября 2016, 17:35:16 Как можно закешировать файлы, чтоб они не скачивались каждый раз заново, хотя бы для конкретного сайта? Не всё всегда возможно, но "Преобразование URL" и регэкспы в помощь... оно для этого в самый раз предназначено.Название: Re: Кеширование по размеру или контенту Отправлено: Terfe от 18 сентября 2016, 19:20:27 Не всё всегда возможно, но "Преобразование URL" и регэкспы в помощь... оно для этого в самый раз предназначено. Повторюсь, ссылки рандомные, типа site.com/fs?AwErT site.com/fs?ByWka site.com/fs?NjSauh и т.д. По таким ссылкам отдаются разные, но повторяющиеся файлы. Каким правилом можно покрыть такие ссылки? Добавлено: 18 Сентябрь 2016, 18:05:33 Что бы не обновлять файлы по размеру используйте расширение eA_Dont_update_file_by_size из дистрибутива HC Пробовал еще до создания темы. Оно сравнивает размер среди одинаковых по имени файлов/ссылок. А у сайта ссылки никогда не повторяются. Нужно, чтоб перед загрузкой НС сравнил размер файла по ссылке с размерами всех файлов в кеше в определённой директории сайта. Если найден файл с таким же размером в кеше, то нужно его выдать браузеру, а файл по ссылке не скачивать. Кто может решить такую задачку? :) Название: Re: Кеширование по размеру или контенту Отправлено: YuS от 18 сентября 2016, 19:22:06 Повторюсь, ссылки рандомные, типа Вам уже подсказали, что необходимы реальные, рабочие ссылки для примера.site.com/fs?AwErT site.com/fs?ByWka site.com/fs?NjSauh и т.д. По таким ссылкам отдаются разные, но повторяющиеся файлы. Каким правилом можно покрыть такие ссылки? Как минимум: 1. Несколько разных ссылок на один файл 2. Несколько разных ссылок на разные файлы 3. Ссылки нужны как формирующие, так и результирующие... А иначе обсуждение не имеет смысла... Название: Re: Кеширование по размеру или контенту Отправлено: alex77 от 19 сентября 2016, 09:24:23 Пробовал еще до создания темы. Оно сравнивает размер среди одинаковых по имени файлов/ссылок. А у сайта ссылки никогда не повторяются. судя по этому задача не решаемая: сайт размер файлов не передает, да и к тому же ссылки сгенерированныеНужно, чтоб перед загрузкой НС сравнил размер файла по ссылке с размерами всех файлов в кеше в определённой директории сайта. Если найден файл с таким же размером в кеше, то нужно его выдать браузеру, а файл по ссылке не скачивать. Кто может решить такую задачку? :) Добавлено: 19 Сентябрь 2016, 16:22:10 Сайт отдает файлы в gzip. Внутри архивов одинаковые имена файлов. ХК точно не умеет "смотреть" внутри архивовНазвание: Re: Кеширование по размеру или контенту Отправлено: Tilks от 19 сентября 2016, 11:05:52 Сайт отдает файлы в gzip. Внутри архивов одинаковые имена файлов. попробовать поправить заголовок запроса, удалив возможность обработать gzip, тогда должен вернуть без сжатия. (строка заголовка Accept-Encoding: gzip, deflate)Название: Re: Кеширование по размеру или контенту Отправлено: Zoynels от 24 сентября 2016, 12:10:46 судя по этому задача не решаемая: сайт размер файлов не передает, да и к тому же ссылки сгенерированные задача думаю решаемая, но только если сервер возвращает Content-Length: сделать расширение которое будет записывать размер файла в байтах вместо имени файла (hc.preform_cache_file_name('site.com\fs\123455 bytes') в AnswerHeaderReceived)Добавлено: 19 Сентябрь 2016, 16:22:10 ХК точно не умеет "смотреть" внутри архивов вот только, если два файла имеют одинаковый размер, но разное содержимое, то будет выдавать только тот который записан в кеше, а не то что вы реально запрашиваете. Название: Re: Кеширование по размеру или контенту Отправлено: kichrot от 21 июля 2018, 14:09:27 Есть сайт, у которого ссылки на файлы являются уникальными, никогда не повторяющимися. Ссылка в виде бессвязного набора символов (генерируется рандомно, видимо). Количество файлов весьма ограничено. Браузер и НС, естественно, закачивают каждый файл по ссылке при навигации по сайту. Как можно закешировать файлы, чтоб они не скачивались каждый раз заново, хотя бы для конкретного сайта? Сайт отдает файлы в gzip. Внутри архивов одинаковые имена файлов. Если не НС, то может есть сторонние средства, которые позволят закешировать по размеру (хотя бы) или контенту? Нашел на просторах интернета расширение которое отлично решает данную проблемму: Код: --[[ <HCExtension> @name content length and type as file name (длина и тип содержимого как имя файла) @author bdstd @version 2.2.1 @exception upload @exception /videoplayback\?.*\&range= @rule fbsbx\.com/file\_download\.php\?id=[^&]+\&.* @rule 4shared.*/download/.*?\?tsid=.* @rule reverbnation\.com/audio\_player/ec @rule media\.sndcdn\.com/.*?\.mp3 @rule \.(3gp|amv|avi|flv|mkv|mpeg|mp4|wmv) @rule /videoplayback\? @rule www[0-9]+\.indowebster\.com/[a-zA-Z0-9]+\.[a-zA-Z0-9]{2,9}$ @rule imgprx.livejournal.net/ @event BeforeViewInMonitor </HCExtension> ]] function cacheable() if re.find(hc.url, [[\&begin=(?!0)[0-9]+]]) or re.find(hc.url, [[redirector]]) or re.find(hc.url, [[^htt[ps]+://\d+\.\d+\.\d+\.\d+.*]]) or re.find(hc.url, [[(\?|\&)(start|starttime)=\d+\.\d+]]) then return false else if re.find(hc.answer_header, [[HTTP/1.1\s200]]) or re.find(hc.answer_header, [[^HTTP/1.1\s206.*?Content\-Range:\sbytes\s0-.*]]) then return true else return false end end end function BeforeViewInMonitor() local x = hc.url if re.match(hc.request_header, [[^X\-Via:\sHandyCache\r\n]]) then hc.request_header = re.replace(hc.request_header, [[^X\-Via:\sHandyCache\r\n]], nil) hc.monitor_string = 'getting_id' hc.call_me_for('AnswerHeaderReceived', 'get_id') else hc.white_mask = 'W' local xdomain = re.replace(x, [[^.*?//(.*?)/.*]], '\\1') local xget = hc.request_header -- local xget = re.replace(xget, [[GET]], 'HEAD') -- beberapa webserver menolak jika menggunakan request method head local xget = re.replace(xget, [[^Range:.*?\r\n]], nil) local xget = re.replace(xget, [[\r\n\r\n]], '\r\nX-Via: HandyCache\r\n\r\n') local xtunnel = 'CONNECT '..xdomain..':443 HTTP/1.1\r\nHost: '..xdomain..'\r\nUser-Agent: HandyCache\r\nConnection: keep-alive\r\n\r\n' if re.find(hc.url, [[^https://]]) then hc.send_request(xget, '', xtunnel) else hc.send_request(xget) end repeat hc.sleep(50) if hc.client_connected=='false' then hc.set_global(x, 'reset') end until hc.get_global(x)~=nil if hc.get_global(x)=='reset' then hc.set_global(x, nil) else if re.find(x, [[\?]]) then hc.request_header = re.replace(hc.request_header, [[(^GET.*?)(\sHTTP/1.1\r\n)]], '\\1&'..hc.get_global(x)..'\\2') hc.call_me_for('URLToFileNameConverting', 'conv') hc.call_me_for('BeforeRequestHeaderSend', 'hit_check') else hc.request_header = re.replace(hc.request_header, [[(^GET.*?)(\sHTTP/1.1\r\n)]], '\\1?'..hc.get_global(x)..'\\2') hc.call_me_for('URLToFileNameConverting', 'conv') hc.call_me_for('BeforeRequestHeaderSend', 'hit_check') end end hc.set_global(x, nil) end end function get_id() if cacheable()==true then local x1 = re.find(hc.answer_header, [[^Content\-Length:\s[0-9]+\r\n]]) local x2 = re.replace(x1, [[^Content\-Length:\s([0-9]+)\r\n]], '\\1') local y1 = re.find(hc.answer_header, [[^Content\-Type:\s[a-zA-Z0-9\-\_]+/[a-zA-Z0-9\-\_]+.*?\r\n]]) local y2 = re.replace(y1, [[^Content\-Type:\s([a-zA-Z0-9\-\_]+)/([a-zA-Z0-9\-\_]+).*?\r\n]], '\\1_\\2') if x2 and y2 then hc.set_global(hc.url, 'x-hc='..x2..'.'..y2) else hc.set_global(hc.url, 'reset') end else hc.set_global(hc.url, 'reset') end hc.client_disconnect() end function conv() local x = hc.url local x = re.replace(x, [[dropboxusercontent]], 'dropbox') local x = re.replace(x, [[^.*?([a-zA-Z0-9\-]{4,20}\.[a-z]{2,3}\.[a-z]{2,3})(/|:\d+/).*x\-hc=(.*)$]], '!content-length-and-type-as-file-name/\\1/\\3') local x = re.replace(x, [[^.*?([a-zA-Z0-9\-]{4,20}\.[a-z]{2,3})(/|:\d+/).*x\-hc=(.*)$]], '!content-length-and-type-as-file-name/\\1/\\3') local x = re.replace(x, [[/]], '\\', true) hc.preform_cache_file_name(x) -- hc.put_msg(x) end function hit_check() if hc.cache_file_name=='' then hc.call_me_for('AnswerHeaderReceived', 'saver') else hc.action = 'dont_update-' hc.monitor_string = 'Hit-Cache' end end function saver() if cacheable()==true then hc.action = 'save-' hc.monitor_string = 'Saving-Content' end end Обратите внимание, что бы расширение работало на конкретном сайте или с адресами обладающими определенными признаками, должно быть в заголовке расширения добавлено правило @rule Название: Re: Кеширование по размеру или контенту Отправлено: kichrot от 30 июля 2018, 21:37:35 Редко, но бывает то, что в заголовке ответа нет Content-Length.
В этом случае для идентификации файла в кэше можно использовать Last-Modified. Доработал для этой ситуации расширение. Внес в него так же некоторые небольшие изменения для удобства применения: Код: --[[ <HCExtension> @name Длина/дата последнего изменения и тип содержимого, как имя файла (LTFN) @author bdstd, kichrot @version 2.2.2 @exception upload @exception /videoplayback\?.*\&range= @exception s.ytimg.com/ @rule fbsbx\.com/file\_download\.php\?id=[^&]+\&.* @rule 4shared.*/download/.*?\?tsid=.* @rule reverbnation\.com/audio\_player/ec @rule imgprx.livejournal.net/ @rule .*ytimg.com/ @rule yt3.ggpht.com/ @event BeforeViewInMonitor </HCExtension> ]] function cacheable() if re.find(hc.url, [[\&begin=(?!0)[0-9]+]]) or re.find(hc.url, [[redirector]]) or re.find(hc.url, [[^htt[ps]+://\d+\.\d+\.\d+\.\d+.*]]) or re.find(hc.url, [[(\?|\&)(start|starttime)=\d+\.\d+]]) then return false else if re.find(hc.answer_header, [[HTTP/1.1\s200]]) or re.find(hc.answer_header, [[^HTTP/1.1\s206.*?Content\-Range:\sbytes\s0-.*]]) then return true else return false end end end function GetContentLength(s) _,_,x = string.find(s, '[cC]ontent%-[lL]ength: *(%d+)') if x==nil then return -1 else return tonumber(x) end end function get_id() if cacheable()==true then local x2 = GetContentLength(hc.answer_header) -- Забираем размер файла из заголовка 'Content-Length' local y1 = re.find(hc.answer_header, [[^Content\-Type:\s[a-zA-Z0-9\-\_]+/[a-zA-Z0-9\-\_]+.*?\r\n]]) local y2 = re.replace(y1, [[^Content\-Type:\s([a-zA-Z0-9\-\_]+)/([a-zA-Z0-9\-\_]+).*?\r\n]], '\\1_\\2') -- если в заголовке нет Content-Length то используем Last-Modified if x2 == -1 then local lmdf = re.find(hc.answer_header, [[^Last-Modified:\s([^\r\n]+)]]) local lmdf = re.replace(lmdf, [[Last-Modified:\s]], '', true) local lmdf = re.replace(lmdf, [[([\s,:])]], '', true) x2 = lmdf -- hc.put_msg(x2) end if x2 ~= -1 and y2 then hc.set_global(hc.url, 'x-hc='..x2..'.'..y2) else hc.set_global(hc.url, 'reset') end else hc.set_global(hc.url, 'reset') end hc.client_disconnect() hc.hide_in_active_list = true hc.hide_in_monitor = true end function conv() local x = hc.url local x = re.replace(x, [[dropboxusercontent]], 'dropbox') local x = re.replace(x, [[^.*?([a-zA-Z0-9\-]{4,20}\.[a-z]{2,3}\.[a-z]{2,3})(/|:\d+/).*x\-hc=(.*)$]], '!content-length-and-type-as-file-name/\\1/\\3') local x = re.replace(x, [[^.*?([a-zA-Z0-9\-]{4,20}\.[a-z]{2,3})(/|:\d+/).*x\-hc=(.*)$]], '!content-length-and-type-as-file-name/\\1/\\3') local x = re.replace(x, [[/]], '\\', true) hc.preform_cache_file_name(x) -- hc.put_msg(x) end function hit_check() if hc.cache_file_name=='' then hc.call_me_for('AnswerHeaderReceived', 'saver') else hc.action = 'dont_update-' hc.monitor_string = 'LTFN-Cache' end end function saver() if cacheable()==true then hc.action = 'save-' hc.monitor_string = 'LTFN-Saving_Content' end end function BeforeViewInMonitor() local x = hc.url if re.match(hc.request_header, [[^X\-Via:\sHandyCache\r\n]]) then hc.request_header = re.replace(hc.request_header, [[^X\-Via:\sHandyCache\r\n]], nil) hc.monitor_string = 'LTFN-getting_id' hc.call_me_for('AnswerHeaderReceived', 'get_id') else hc.white_mask = 'W' local xdomain = re.replace(x, [[^.*?//(.*?)/.*]], '\\1') local xget = hc.request_header -- local xget = re.replace(xget, [[GET]], 'HEAD') -- некоторый веб-сервер отклоняется, если использует метод метода запроса local xget = re.replace(xget, [[^Range:.*?\r\n]], nil) local xget = re.replace(xget, [[\r\n\r\n]], '\r\nX-Via: HandyCache\r\n\r\n') local xtunnel = 'CONNECT '..xdomain..':443 HTTP/1.1\r\nHost: '..xdomain..'\r\nUser-Agent: HandyCache\r\nConnection: keep-alive\r\n\r\n' if re.find(hc.url, [[^https://]]) then hc.send_request(xget, '', xtunnel) else hc.send_request(xget) end repeat hc.sleep(50) if hc.client_connected=='false' then hc.set_global(x, 'reset') end until hc.get_global(x)~=nil if hc.get_global(x)=='reset' then hc.set_global(x, nil) else if re.find(x, [[\?]]) then hc.request_header = re.replace(hc.request_header, [[(^GET.*?)(\sHTTP/1.1\r\n)]], '\\1&'..hc.get_global(x)..'\\2') hc.call_me_for('URLToFileNameConverting', 'conv') hc.call_me_for('BeforeRequestHeaderSend', 'hit_check') else hc.request_header = re.replace(hc.request_header, [[(^GET.*?)(\sHTTP/1.1\r\n)]], '\\1?'..hc.get_global(x)..'\\2') hc.call_me_for('URLToFileNameConverting', 'conv') hc.call_me_for('BeforeRequestHeaderSend', 'hit_check') end end hc.set_global(x, nil) end end Название: Re: Кеширование по размеру или контенту Отправлено: kichrot от 03 августа 2018, 19:26:35 Помещаю последнюю версию расширения.
Изменения: 1) имя файла в кеше формируется из значений 'Content-Length' и 'Last-Modified' содержащихся в заголовке ответа сервера. Если одного из этих значений в заголовке ответа сервера нет, то оно заменяется на "-1". В качестве расширения файла используется значение 'Content-Type' из заголовка ответа сервера. Примеры имен файлов в кеше, образуемых расширением, на основе содержимого заголовка ответа сервера: - "727617_Fri20Jul2018205327GMT.image_png" - "297011_-1.image_jpeg" - "-1_Mon16Jul2018093938GMT.image_jpeg" В результате такой политики, образования имен файлов, степень идентификации файлов в кэше существенно увеличивается, а вероятность совпадения имен у различных файлов существенно уменьшается. 2) исправлена ошибка в коде приводящая к записи в кеш пустых каталогов. Код: --[[ <HCExtension> @name Длина/дата последнего изменения и тип содержимого, как имя файла (LDTFN) @author bdstd, kichrot @version 2.2.4 @exception upload @exception /videoplayback\?.*\&range= @exception s.ytimg.com/ @rule fbsbx\.com/file\_download\.php\?id=[^&]+\&.* @rule 4shared.*/download/.*?\?tsid=.* @rule reverbnation\.com/audio\_player/ec @rule imgprx.livejournal.net/ @rule .*ytimg.com/ @rule yt3.ggpht.com/ @event BeforeViewInMonitor </HCExtension> ]] function cacheable() if re.find(hc.url, [[\&begin=(?!0)[0-9]+]]) or re.find(hc.url, [[redirector]]) or re.find(hc.url, [[^htt[ps]+://\d+\.\d+\.\d+\.\d+.*]]) or re.find(hc.url, [[(\?|\&)(start|starttime)=\d+\.\d+]]) then return false else if re.find(hc.answer_header, [[HTTP/1.1\s200]]) or re.find(hc.answer_header, [[^HTTP/1.1\s206.*?Content\-Range:\sbytes\s0-.*]]) then return true else return false end end end function GetContentLength(s) _,_,x = string.find(s, '[cC]ontent%-[lL]ength: *(%d+)') if x==nil then return -1 else return tonumber(x) end end function GetLastModified(d) x = re.find(d, [[^[lL]ast-[mM]odified:\s]]) -- hc.put_msg(x) if x then x = re.find(d, [[^[lL]ast-[mM]odified:\s([^\r\n]+)]]) x = re.replace(x, [[[lL]ast-[mM]odified:\s]], '', true) x = re.replace(x, [[([\s,:])]], '', true) return x else return -1 end end function get_id() hc.action = 'dont_save' hc.client_disconnect() hc.hide_in_active_list = true hc.hide_in_monitor = true if cacheable()==true then local z = GetLastModified(hc.answer_header) -- Забираем время последнего изменения файла из заголовка 'Last-Modified' local x1 = GetContentLength(hc.answer_header) -- Забираем размер файла из заголовка 'Content-Length' local x2 = x1 .. '_' .. z local y1 = re.find(hc.answer_header, [[^Content\-Type:\s[a-zA-Z0-9\-\_]+/[a-zA-Z0-9\-\_]+.*?\r\n]]) local y2 = re.replace(y1, [[^Content\-Type:\s([a-zA-Z0-9\-\_]+)/([a-zA-Z0-9\-\_]+).*?\r\n]], '\\1_\\2') -- hc.put_msg(x2) if x2 and y2 then hc.set_global(hc.url, 'x-hc='..x2..'.'..y2) else hc.set_global(hc.url, 'reset') end else hc.set_global(hc.url, 'reset') end end function conv() local x = hc.url local x = re.replace(x, [[dropboxusercontent]], 'dropbox') local x = re.replace(x, [[^.*?([a-zA-Z0-9\-]{4,20}\.[a-z]{2,3}\.[a-z]{2,3})(/|:\d+/).*x\-hc=(.*)$]], '!content-length-and-type-as-file-name/\\1/\\3') local x = re.replace(x, [[^.*?([a-zA-Z0-9\-]{4,20}\.[a-z]{2,3})(/|:\d+/).*x\-hc=(.*)$]], '!content-length-and-type-as-file-name/\\1/\\3') local x = re.replace(x, [[/]], '\\', true) hc.preform_cache_file_name(x) -- hc.put_msg(x) end function saver() if cacheable()==true then hc.action = 'save-' hc.monitor_string = 'LDTFN-Saving_Content' end end function hit_check() if hc.cache_file_name=='' then hc.call_me_for('AnswerHeaderReceived', 'saver') else hc.action = 'dont_update-' hc.monitor_string = 'LDTFN-Cache' end end function BeforeViewInMonitor() local x = hc.url if re.match(hc.request_header, [[^X\-Via:\sHandyCache\r\n]]) then hc.request_header = re.replace(hc.request_header, [[^X\-Via:\sHandyCache\r\n]], nil) hc.monitor_string = 'LDTFN-getting_id' hc.call_me_for('AnswerHeaderReceived', 'get_id') else hc.white_mask = 'W' local xdomain = re.replace(x, [[^.*?//(.*?)/.*]], '\\1') local xget = hc.request_header -- local xget = re.replace(xget, [[GET]], 'HEAD') -- beberapa webserver menolak jika menggunakan request method head local xget = re.replace(xget, [[^Range:.*?\r\n]], nil) local xget = re.replace(xget, [[\r\n\r\n]], '\r\nX-Via: HandyCache\r\n\r\n') local xtunnel = 'CONNECT '..xdomain..':443 HTTP/1.1\r\nHost: '..xdomain..'\r\nUser-Agent: HandyCache\r\nConnection: keep-alive\r\n\r\n' if re.find(hc.url, [[^https://]]) then hc.send_request(xget, '', xtunnel) else hc.send_request(xget) end repeat hc.sleep(50) if hc.client_connected=='false' then hc.set_global(x, 'reset') end until hc.get_global(x)~=nil if hc.get_global(x)=='reset' then hc.set_global(x, nil) else if re.find(x, [[\?]]) then hc.request_header = re.replace(hc.request_header, [[(^GET.*?)(\sHTTP/1.1\r\n)]], '\\1&'..hc.get_global(x)..'\\2') hc.call_me_for('URLToFileNameConverting', 'conv') hc.call_me_for('BeforeRequestHeaderSend', 'hit_check') else hc.request_header = re.replace(hc.request_header, [[(^GET.*?)(\sHTTP/1.1\r\n)]], '\\1?'..hc.get_global(x)..'\\2') hc.call_me_for('URLToFileNameConverting', 'conv') hc.call_me_for('BeforeRequestHeaderSend', 'hit_check') end end hc.set_global(x, nil) end end Название: Re: Кеширование по размеру или контенту Отправлено: LordMerlin от 04 августа 2018, 10:22:44 В качестве расширения файла используется значение 'Content-Type' из заголовка ответа сервера. Можно узнать, в чем великий эротический смысл этого действа? Почему нельзя оставить родное расширение?Название: Re: Кеширование по размеру или контенту Отправлено: kichrot от 04 августа 2018, 14:54:49 Можно узнать, в чем великий эротический смысл этого действа? Почему нельзя оставить родное расширение? Попытаюсь обосновать. Возьмем два примера заголовков запросов браузера и ответов сервера: 1) http://imgprx.livejournal.net/337edab331ea43fc35777cf0bb4774596402a46d/1keziXqj4zh9nezCiCQjkfcsFVcK9yq6cFQG1ip_yEAX0-J-SdJErtxXn2wAEuWzL_UHq9WsNey5rPnGvSTGNBp5KodlCWVM9dmLHSfQSkjVVuLrzia9z6lKImSNNsoZyWFQVEeFOTFNCTZIfhGUCw GET /337edab331ea43fc35777cf0bb4774596402a46d/1keziXqj4zh9nezCiCQjkfcsFVcK9yq6cFQG1ip_yEAX0-J-SdJErtxXn2wAEuWzL_UHq9WsNey5rPnGvSTGNBp5KodlCWVM9dmLHSfQSkjVVuLrzia9z6lKImSNNsoZyWFQVEeFOTFNCTZIfhGUCw HTTP/1.1 Host: imgprx.livejournal.net User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Connection: keep-alive Upgrade-Insecure-Requests: 1 HTTP/1.1 200 OK Server: HandyCache/Version 1.00 RC4 (1.0.0.833) Content-Length: 122814 Connection: Keep-alive Last-Modified: Sat, 04 Aug 2018 11:44:30 GMT Content-Type: image/png 2) http://imgprx.livejournal.net/07b0c8dd551a0edf3d662b2a9d85944ab288ac6b/uRegMDGRz-WDc80QTfat7Gl1ghiMCL7L1YIC7SEryR6CprmSKITT94HqQ1Q_Bl5p35mvP1r-WjbP0uTojE7OEGIfu8CQfRZk2ciVUnB4eq2M0KlZ-mILDphBQMPiBIwVnYtJHkNWqHTFPRNPDc081rvICLReqIAHmq3KGVycvw-sYnMZ2-QzahuHQsaShaj8V4J4EnpLBgNuS5xtqfhuCE-VD_EuW7HMNNJvdD06wj4 GET /07b0c8dd551a0edf3d662b2a9d85944ab288ac6b/uRegMDGRz-WDc80QTfat7Gl1ghiMCL7L1YIC7SEryR6CprmSKITT94HqQ1Q_Bl5p35mvP1r-WjbP0uTojE7OEGIfu8CQfRZk2ciVUnB4eq2M0KlZ-mILDphBQMPiBIwVnYtJHkNWqHTFPRNPDc081rvICLReqIAHmq3KGVycvw-sYnMZ2-QzahuHQsaShaj8V4J4EnpLBgNuS5xtqfhuCE-VD_EuW7HMNNJvdD06wj4 HTTP/1.1 Host: imgprx.livejournal.net User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Connection: keep-alive Upgrade-Insecure-Requests: 1 HTTP/1.1 200 OK Server: HandyCache/Version 1.00 RC4 (1.0.0.833) Content-Length: 22334 Connection: Keep-alive Last-Modified: Sat, 04 Aug 2018 11:44:28 GMT Content-Type: image/webp Как Вы можете наблюдать, сервер выдает файлы вообще без расширений. Конечно, можно написать код, который будет, на основании заголовков ответа сервера, формировать расширения файлов стандартного вида. Но зачем??? Это только приведет к усложнению кода расширения HC. Если Вам так необходимо, то ни кто и ни что не мешает изменить код расширения на требуемый Вам. Название: Re: Кеширование по размеру или контенту Отправлено: Zork от 04 августа 2018, 18:10:47 А откуда HandyCache/Version 1.00 RC4 (1.0.0.833), если на сайте последняя HandyCache RC4 1.0.0.700 ?
Название: Re: Кеширование по размеру или контенту Отправлено: kichrot от 04 августа 2018, 19:48:53 Можно узнать, в чем великий эротический смысл этого действа? Почему нельзя оставить родное расширение? Почесал репу, подумал и исправил указанную Вами порнографию. Теперь имена файлов в кэше получают нормальные стандартные расширения. Выкладываю исправленную версию: Код: --[[ <HCExtension> @name Длина, дата последнего изменения и тип содержимого, как имя файла (LDTFN) @author bdstd, kichrot @version 2.2.5 @exception upload @exception /videoplayback\?.*\&range= @exception s.ytimg.com/ @rule imgprx.livejournal.net/ @rule .*ytimg.com/ @rule yt3.ggpht.com/ @event BeforeViewInMonitor </HCExtension> ]] function cacheable() if re.find(hc.url, [[\&begin=(?!0)[0-9]+]]) or re.find(hc.url, [[redirector]]) or re.find(hc.url, [[^htt[ps]+://\d+\.\d+\.\d+\.\d+.*]]) or re.find(hc.url, [[(\?|\&)(start|starttime)=\d+\.\d+]]) then return false else if re.find(hc.answer_header, [[HTTP/1.1\s200]]) or re.find(hc.answer_header, [[^HTTP/1.1\s206.*?Content\-Range:\sbytes\s0-.*]]) then return true else return false end end end function GetContentType(s) _,_,x = string.find(s, '[cC]ontent%-[tT]ype: *([^;\r\n]+)') if x~=nil then x = string.lower(x) end return x end function GetContentLength(s) _,_,x = string.find(s, '[cC]ontent%-[lL]ength: *(%d+)') if x==nil then return -1 else return tonumber(x) end end function GetLastModified(d) x = re.find(d, [[^[lL]ast-[mM]odified:\s]]) -- hc.put_msg(x) if x then x = re.find(d, [[^[lL]ast-[mM]odified:\s([^\r\n]+)]]) x = re.replace(x, [[[lL]ast-[mM]odified:\s]], '', true) x = re.replace(x, [[([\s,:])]], '', true) return x else return -1 end end function get_id() hc.action = 'dont_save' hc.client_disconnect() hc.hide_in_active_list = true hc.hide_in_monitor = true if cacheable()==true then local z = GetLastModified(hc.answer_header) -- Забираем время последнего изменения файла из заголовка 'Last-Modified' local x1 = GetContentLength(hc.answer_header) -- Забираем размер файла из заголовка 'Content-Length' local x2 = x1 .. '_' .. z local y1 = GetContentType(hc.answer_header) -- Забираем тип файла из заголовка 'Content-Type' local y2 = re.replace(y1, [[(.+?(?=/)+/)]], '', true) if x2 and y2 then hc.set_global(hc.url, 'x-hc='..x2..'.'..y2) else hc.set_global(hc.url, 'reset') end else hc.set_global(hc.url, 'reset') end end function conv() local x = hc.url local x = re.replace(x, [[dropboxusercontent]], 'dropbox') local x = re.replace(x, [[^.*?([a-zA-Z0-9\-]{4,20}\.[a-z]{2,3}\.[a-z]{2,3})(/|:\d+/).*x\-hc=(.*)$]], '!content-length-and-type-as-file-name/\\1/\\3') local x = re.replace(x, [[^.*?([a-zA-Z0-9\-]{4,20}\.[a-z]{2,3})(/|:\d+/).*x\-hc=(.*)$]], '!content-length-and-type-as-file-name/\\1/\\3') local x = re.replace(x, [[/]], '\\', true) hc.preform_cache_file_name(x) -- hc.put_msg(x) end function saver() if cacheable()==true then hc.action = 'save-' hc.monitor_string = 'LDTFN-Saving_Content' end end function hit_check() if hc.cache_file_name=='' then hc.call_me_for('AnswerHeaderReceived', 'saver') else hc.action = 'dont_update-' hc.monitor_string = 'LDTFN-Cache' end end function BeforeViewInMonitor() local x = hc.url if re.match(hc.request_header, [[^X\-Via:\sHandyCache\r\n]]) then hc.request_header = re.replace(hc.request_header, [[^X\-Via:\sHandyCache\r\n]], nil) hc.monitor_string = 'LDTFN-getting_id' hc.call_me_for('AnswerHeaderReceived', 'get_id') else hc.white_mask = 'W' local xdomain = re.replace(x, [[^.*?//(.*?)/.*]], '\\1') local xget = hc.request_header -- local xget = re.replace(xget, [[GET]], 'HEAD') -- beberapa webserver menolak jika menggunakan request method head local xget = re.replace(xget, [[^Range:.*?\r\n]], nil) local xget = re.replace(xget, [[\r\n\r\n]], '\r\nX-Via: HandyCache\r\n\r\n') local xtunnel = 'CONNECT '..xdomain..':443 HTTP/1.1\r\nHost: '..xdomain..'\r\nUser-Agent: HandyCache\r\nConnection: keep-alive\r\n\r\n' if re.find(hc.url, [[^https://]]) then hc.send_request(xget, '', xtunnel) else hc.send_request(xget) end repeat hc.sleep(50) if hc.client_connected=='false' then hc.set_global(x, 'reset') end until hc.get_global(x)~=nil if hc.get_global(x)=='reset' then hc.set_global(x, nil) else if re.find(x, [[\?]]) then hc.request_header = re.replace(hc.request_header, [[(^GET.*?)(\sHTTP/1.1\r\n)]], '\\1&'..hc.get_global(x)..'\\2') hc.call_me_for('URLToFileNameConverting', 'conv') hc.call_me_for('BeforeRequestHeaderSend', 'hit_check') else hc.request_header = re.replace(hc.request_header, [[(^GET.*?)(\sHTTP/1.1\r\n)]], '\\1?'..hc.get_global(x)..'\\2') hc.call_me_for('URLToFileNameConverting', 'conv') hc.call_me_for('BeforeRequestHeaderSend', 'hit_check') end end hc.set_global(x, nil) end end Название: Re: Кеширование по размеру или контенту Отправлено: kichrot от 05 августа 2018, 23:43:32 После того, как расширение научилось давать файлам в кэше стандартные расширения вылезла проблема связанная с конфликтом со списками и другими расширениями. Но вроде бы решил проблему.
Выкладываю доработанную версию расширения: Код: --[[ <HCExtension> @name Длина, дата последнего изменения и тип содержимого, как имя файла (LDTFN) @author bdstd, kichrot @version 2.2.6 @rule imgprx.livejournal.net/ @event BeforeViewInMonitor </HCExtension> ]] function cacheable() if re.find(hc.url, [[\&begin=(?!0)[0-9]+]]) or re.find(hc.url, [[redirector]]) or re.find(hc.url, [[^htt[ps]+://\d+\.\d+\.\d+\.\d+.*]]) or re.find(hc.url, [[(\?|\&)(start|starttime)=\d+\.\d+]]) then return false else if re.find(hc.answer_header, [[HTTP/1.1\s200]]) or re.find(hc.answer_header, [[^HTTP/1.1\s206.*?Content\-Range:\sbytes\s0-.*]]) then return true else return false end end end function GetContentType(s) _,_,x = string.find(s, '[cC]ontent%-[tT]ype: *([^;\r\n]+)') if x~=nil then x = string.lower(x) end return x end function GetContentLength(s) _,_,x = string.find(s, '[cC]ontent%-[lL]ength: *(%d+)') if x==nil then return -1 else return tonumber(x) end end function GetLastModified(d) x = re.find(d, [[^[lL]ast-[mM]odified:\s]]) -- hc.put_msg(x) if x then x = re.find(d, [[^[lL]ast-[mM]odified:\s([^\r\n]+)]]) x = re.replace(x, [[[lL]ast-[mM]odified:\s]], '', true) x = re.replace(x, [[([\s,:])]], '', true) return x else return -1 end end function get_id() hc.white_mask="ЗНП" hc.action = 'dont_save' hc.client_disconnect() hc.hide_in_active_list = true hc.hide_in_monitor = true if cacheable()==true then local z = GetLastModified(hc.answer_header) -- Забираем время последнего изменения файла из заголовка 'Last-Modified' local x1 = GetContentLength(hc.answer_header) -- Забираем размер файла из заголовка 'Content-Length' local x2 = x1 .. '_' .. z local y1 = GetContentType(hc.answer_header) -- Забираем тип файла из заголовка 'Content-Type' -- local y2 = re.replace(y1, [[([/])]], '_', true) local y2 = re.replace(y1, [[(.+?(?=/)+/)]], '', true) -- hc.put_msg(y2) if x2 and y2 then hc.set_global(hc.url, 'x-hc='..x2..'.'..y2) hc.white_mask="Н" else hc.set_global(hc.url, 'reset') end else hc.set_global(hc.url, 'reset') end end function conv() local x = hc.url local x = re.replace(x, [[dropboxusercontent]], 'dropbox') local x = re.replace(x, [[^.*?([a-zA-Z0-9\-]{4,20}\.[a-z]{2,3}\.[a-z]{2,3})(/|:\d+/).*x\-hc=(.*)$]], '!content-length-and-type-as-file-name/\\1/\\3') local x = re.replace(x, [[^.*?([a-zA-Z0-9\-]{4,20}\.[a-z]{2,3})(/|:\d+/).*x\-hc=(.*)$]], '!content-length-and-type-as-file-name/\\1/\\3') local x = re.replace(x, [[/]], '\\', true) hc.preform_cache_file_name(x) -- hc.put_msg(x) end function saver() if cacheable()==true then hc.action = 'save' hc.monitor_string = 'LDTFN-Saving_Content' end end function hit_check() if hc.cache_file_name=='' then hc.call_me_for('AnswerHeaderReceived', 'saver') else hc.white_mask="З" hc.action = 'dont_update' hc.monitor_string = 'LDTFN-Cache' end end function BeforeViewInMonitor() local x = hc.url if re.match(hc.request_header, [[^X\-Via:\sHandyCache\r\n]]) then hc.request_header = re.replace(hc.request_header, [[^X\-Via:\sHandyCache\r\n]], nil) hc.monitor_string = 'LDTFN-getting_id' hc.call_me_for('AnswerHeaderReceived', 'get_id') else hc.white_mask = 'W' local xdomain = re.replace(x, [[^.*?//(.*?)/.*]], '\\1') local xget = hc.request_header -- local xget = re.replace(xget, [[GET]], 'HEAD') -- beberapa webserver menolak jika menggunakan request method head local xget = re.replace(xget, [[^Range:.*?\r\n]], nil) local xget = re.replace(xget, [[\r\n\r\n]], '\r\nX-Via: HandyCache\r\n\r\n') local xtunnel = 'CONNECT '..xdomain..':443 HTTP/1.1\r\nHost: '..xdomain..'\r\nUser-Agent: HandyCache\r\nConnection: keep-alive\r\n\r\n' if re.find(hc.url, [[^https://]]) then hc.send_request(xget, '', xtunnel) else hc.send_request(xget) end repeat hc.sleep(50) if hc.client_connected=='false' then hc.set_global(x, 'reset') end until hc.get_global(x)~=nil if hc.get_global(x)=='reset' then hc.set_global(x, nil) else hc.white_mask="Н" if re.find(x, [[\?]]) then hc.request_header = re.replace(hc.request_header, [[(^GET.*?)(\sHTTP/1.1\r\n)]], '\\1&'..hc.get_global(x)..'\\2') hc.call_me_for('URLToFileNameConverting', 'conv') hc.call_me_for('BeforeRequestHeaderSend', 'hit_check') else hc.request_header = re.replace(hc.request_header, [[(^GET.*?)(\sHTTP/1.1\r\n)]], '\\1?'..hc.get_global(x)..'\\2') hc.call_me_for('URLToFileNameConverting', 'conv') hc.call_me_for('BeforeRequestHeaderSend', 'hit_check') end end hc.set_global(x, nil) end end Название: Re: Кеширование по размеру или контенту Отправлено: hc.addict от 06 августа 2018, 07:36:17 Есть сайт, у которого ссылки на файлы являются уникальными, никогда не повторяющимися. Ссылка в виде бессвязного набора символов (генерируется рандомно, видимо). Количество файлов весьма ограничено. Браузер и НС, естественно, закачивают каждый файл по ссылке при навигации по сайту. Как можно закешировать файлы, чтоб они не скачивались каждый раз заново, хотя бы для конкретного сайта? Сайт отдает файлы в gzip. Внутри архивов одинаковые имена файлов. Если не НС, то может есть сторонние средства, которые позволят закешировать по размеру (хотя бы) или контенту? Youtube stream url is an example of this. Название: Re: Кеширование по размеру или контенту Отправлено: kichrot от 14 августа 2018, 10:55:04 Тестирую предлагаемое мной расширение на основе адресов с сервера imgprx.livejournal.net, который хранит ссылки на картинки для блогов livejournal.com.
По итогам тестов внес очередные изменения в расширение, улучшающие его потребительские свойства и стабильность: Код: --[[ <HCExtension> @name Длина, дата последнего изменения и тип содержимого, как имя файла (LDTFN) @author bdstd, kichrot @version 2.2.9 @rule imgprx.livejournal.net/ @event BeforeViewInMonitor </HCExtension> ]] function cacheable() if re.find(hc.url, [[\&begin=(?!0)[0-9]+]]) or re.find(hc.url, [[redirector]]) or re.find(hc.url, [[^htt[ps]+://\d+\.\d+\.\d+\.\d+.*]]) or re.find(hc.url, [[(\?|\&)(start|starttime)=\d+\.\d+]]) then return false else if re.find(hc.answer_header, [[HTTP/1.1\s200]]) or re.find(hc.answer_header, [[^HTTP/1.1\s206.*?Content\-Range:\sbytes\s0-.*]]) then return true else return false end end end function GetContentType(s) _,_,x = string.find(s, '[cC]ontent%-[tT]ype: *([^;\r\n]+)') if x~=nil then x = string.lower(x) end return x end function GetContentLength(s) _,_,x = string.find(s, '[cC]ontent%-[lL]ength: *(%d+)') if x==nil then return -1 else return tonumber(x) end end function GetLastModified(d) local x = re.find(d, [[^[lL]ast-[mM]odified:\s]]) if x then x = re.find(d, [[^[lL]ast-[mM]odified:\s([^\r\n]+)]]) x = re.replace(x, [[[lL]ast-[mM]odified:\s]], '', true) return x else return -1 end end function GetAnswerCode(s) _,_,x = string.find(s, 'HTTP/1%.%d +(%d+)') if x==nil then return -1 else return tonumber(x) end end function get_id() hc.monitor_string = 'LDTFN-getting_id' hc.white_mask="ЗНП" hc.action = 'dont_save' hc.client_disconnect() hc.hide_in_active_list = true hc.hide_in_monitor = true if cacheable()==true then local z = GetLastModified(hc.answer_header) -- Забираем время последнего изменения файла из заголовка 'Last-Modified' z = re.replace(z, [[([\s,:])]], '', true) -- Убираем пробелы из значения 'Last-Modified' local x1 = GetContentLength(hc.answer_header) -- Забираем размер файла из заголовка 'Content-Length' local x2 = x1 .. '_' .. z local y1 = GetContentType(hc.answer_header) -- Забираем тип файла из заголовка 'Content-Type' -- local y2 = re.replace(y1, [[([/])]], '_', true) local y2 = re.replace(y1, [[(.+?(?=/)+/)]], '', true) -- hc.put_msg(y2) if x2 and y2 then hc.set_global(hc.url, 'x-hc='..x2..'.'..y2) hc.white_mask="Н" else hc.set_global(hc.url, 'reset') end else hc.set_global(hc.url, 'reset') end end function conv() local x = hc.url local x = re.replace(x, [[dropboxusercontent]], 'dropbox') local x = re.replace(x, [[^.*?([a-zA-Z0-9\-]{4,20}\.[a-z]{2,3}\.[a-z]{2,3})(/|:\d+/).*x\-hc=(.*)$]], '!content-length-and-type-as-file-name/\\1/\\3') local x = re.replace(x, [[^.*?([a-zA-Z0-9\-]{4,20}\.[a-z]{2,3})(/|:\d+/).*x\-hc=(.*)$]], '!content-length-and-type-as-file-name/\\1/\\3') local x = re.replace(x, [[/]], '\\', true) hc.preform_cache_file_name(x) -- hc.put_msg(x) end function saver() if cacheable()==true then hc.action = 'save' hc.monitor_string = 'LDTFN-Saving' end end function hit_check() if hc.cache_file_name=='' then hc.call_me_for('AnswerHeaderReceived', 'saver') else hc.white_mask="З" hc.action = 'dont_update' hc.monitor_string = 'LDTFN-Cache' end end function BeforeViewInMonitor() -- выясняем код ответа из заголовка local answ_code = GetAnswerCode(hc.answer_header) -- если код ответа не равен 301, 302, 303, 307, 308 if answ_code~=301 and answ_code~=302 and answ_code~=303 and answ_code~=307 and answ_code~=308 then local x = hc.url if re.match(hc.request_header, [[^X\-Via:\sHandyCache\r\n]]) then hc.request_header = re.replace(hc.request_header, [[^X\-Via:\sHandyCache\r\n]], nil) hc.call_me_for('AnswerHeaderReceived', 'get_id') else hc.white_mask = 'W' local xdomain = re.replace(x, [[^.*?//(.*?)/.*]], '\\1') local xget = hc.request_header -- local xget = re.replace(xget, [[GET]], 'HEAD') -- beberapa webserver menolak jika menggunakan request method head local xget = re.replace(xget, [[^Range:.*?\r\n]], nil) local xget = re.replace(xget, [[\r\n\r\n]], '\r\nX-Via: HandyCache\r\n\r\n') local xtunnel = 'CONNECT '..xdomain..':443 HTTP/1.1\r\nHost: '..xdomain..'\r\nUser-Agent: HandyCache\r\nConnection: keep-alive\r\n\r\n' if re.find(hc.url, [[^https://]]) then hc.send_request(xget, '', xtunnel) else hc.send_request(xget) end repeat hc.sleep(50) if hc.client_connected=='false' then hc.set_global(x, 'reset') end until hc.get_global(x)~=nil if hc.get_global(x)=='reset' then hc.set_global(x, nil) else hc.white_mask="Н" if re.find(x, [[\?]]) then hc.request_header = re.replace(hc.request_header, [[(^GET.*?)(\sHTTP/1.1\r\n)]], '\\1&'..hc.get_global(x)..'\\2') hc.call_me_for('URLToFileNameConverting', 'conv') hc.call_me_for('BeforeRequestHeaderSend', 'hit_check') else hc.request_header = re.replace(hc.request_header, [[(^GET.*?)(\sHTTP/1.1\r\n)]], '\\1?'..hc.get_global(x)..'\\2') hc.call_me_for('URLToFileNameConverting', 'conv') hc.call_me_for('BeforeRequestHeaderSend', 'hit_check') end end hc.set_global(x, nil) end end end Как показывает моя практика, с данным расширением следует использовать расширение которое запрещает сохранять в кэше ответы сервера с кодами 301, 302, 303, 307 и 308: Код: --[[ <HCExtension> @name Не сохранять ответ 301, 302, 303, 307 и 308 (30(x) Dont_save ) @author kichrot @version 0.1 @description Не сохранять файл в заголовке которого ответ сервера "HTTP/1.1 30X ..." @event AnswerHeaderReceived/Answer </HCExtension> ]] function GetAnswerCode(s) _,_,x = string.find(s, 'HTTP/1%.%d +(%d+)') if x==nil then return -1 else return tonumber(x) end end function Answer() -- выясняем код ответа из заголовка answ_code = GetAnswerCode(hc.answer_header) -- если код ответа 301, 302, 303, 307 или 308 if answ_code==301 or answ_code==302 or answ_code==303 or answ_code==307 or answ_code==308 then hc.action = 'dont_save' hc.monitor_string = hc.monitor_string..'30(x) Dont_save ' end end -- Конец функции Answer Название: Re: Кеширование по размеру или контенту Отправлено: hc.addict от 17 августа 2018, 19:35:38 @kichrot:
I prefer simple and direct. Код: function GetAnswerCode(s) _,_,x = string.find(s,'HTTP/1%.%d +(%d+)') if x==nil then return -1 else return tonumber(x) end end function Answer() local answ_code = GetAnswerCode(hc.answer_header) if answ_code == 200 then hc.action = 'save' hc.monitor_string = 'Save' end end
Powered by SMF 1.1.3 SMF © 2006, Simple Machines LLC
Joomla Bridge by JoomlaHacks.com |