Search Preview — расширение для Chrome
О расширении
Данное расширение предоставляет возможность просматривать сайт результата поиска в Google, что значительно сокращает время на поиск и обработку информации.
Предыстория
После того как Google закрыла проект Instant Preview, поиск нужной информации стал занимать гораздо больше времени, открытых вкладок и нервов! :(После чего я решил исправить данную ситуацию и написать небольшое расширение облегчающее мне жизнь.Разработка
Благодаря тому, что в Google Chrome поддерживалась технология HTML5 (а именно iframe sandbox), реализовать расширение не составило труда и за один вечер был написан прототип. Я несомненно был рад этому, но было печально за других людей, которые тоже были жертвами закрытия Instant Preview. Поэтому решил выложить в открытый доступ расширение.Само расширение базировалось на возможности загружать в iframe любую страницу при этом атрибут sandbox позволял отключать javascript и редирект главного окна т.е. нельзя было выполнить из iframe такой код
top.location =
Поиск решения Но меня это не остановило, было интересно решить данную проблему. Первое что пришло на ум использовать web proxy, т.е. в iframe загружать данные не напрямую с сайта, а через web proxy по защищенному протоколу https тем самым решалась проблема с незащищенным контентом, а также web proxy мог обрезать заголовок X-Frame-Options.На разработку своего web proxy не хотелось тратить время, задачу нужно решить быстро. Немного погуглив я наткнулся на данный скрипт google-proxy — это web proxy для appengine написан на python. Установив его и выкатив новую версию расширения, я не надолго забыл о проблеме. Но проблема пришла вновь в виде нехватки бесплатной квоты appengine, пришлось делать несколько зеркал для web proxy. Сделав четыре зеркала казалось, что всё хорошо, но в отзывах расширения мне написали, что опять появляется ошибка нехватки квоты. В appengine квота обнуляется каждые 24 часа, т.е. в то время когда я пользуюсь расширением квоты еще хватает, а вот для жителей другого края света :) квота уже исчерпана.
Свой web proxy Немного подумав я решил всё таки потратить время на написание web proxy и выбрал язык Go. На освоение языка Go ушло немного времени, т.к. до этого я писал на нём небольшие скрипты в обучающих целях. Но с разработкой web сервера на Go не сталкивался. Почитав документацию и выбрав в качестве web инструмента gorillatoolkit, а именно роутер gorilla/mux. Писать роутер довольно легко: r:= mux.NewRouter () r.HandleFunc (»/env», environ) r.HandleFunc (»/web_proxy», web_proxy.WebProxyHandler) r.PathPrefix (»/»).Handler (http.StripPrefix (»/», http.FileServer (http.Dir (staticDir)))) r.Methods («GET») Дальше для замены ссылок и адресов, чистки html выбрал библиотеку gokogiri это оболочка к libxml. Нужно было все адреса (url) зароутить на мой web proxy скрипт. Потом отключил некоторые теги полностью удалив их из DOM в том числе и тег script. Интерактивность preview сайта не нужна. CSS были тоже обработаны, т.к. там встречаются url картинок, шрифтов и т.д.
Получается такой меппинг тегов при обходе DOM вызывается функция соответствующая тегу.
var ( nodeElements = map[string]func (*context, xml.Node){ // proxy URL «a»: proxyURL («href»), «img»: proxyURL («src»), «link»: proxyURL («href»), «iframe»: proxyURL («src»), // normalize URL «object»: normalizeURL («src»), «embed»: normalizeURL («src»), «audio»: normalizeURL («src»), «video»: normalizeURL («src»), // remove Node «script»: removeNode, «base»: removeNode, // style css «style»: proxyCSSURL, }
xpathElements string = createXPath ()
includeScripts = []string{ »/js/analytics.js», }
cssURLPattern = regexp.MustCompile (`url\s*\(\s*(?:[»']?)([^\)]+?)(?:[»']?)\s*\)`) ) Фильтрация html.
func filterHTML (t *WebTransport, body, encoding []byte, baseURL *url.URL) ([]byte, error) { if encoding == nil { encoding = html.DefaultEncodingBytes }
doc, err:= html.Parse (body, encoding, []byte (baseURL.String ()), html.DefaultParseOption, encoding)
if err!= nil { return []byte (»), err } defer doc.Free ()
c:= &context{t: t, baseURL: baseURL} nodes, err:= doc.Root ().Search (xpathElements) if err == nil { for _, node:= range (nodes) { name:= strings.ToLower (node.Name ()) nodeElements[name](c, node) }
} // add scripts addScripts (doc)
return []byte (doc.String ()), nil } Фильтрация CSS
func filterCSS (t *WebTransport, body, encoding []byte, baseURL *url.URL) ([]byte, error) { cssReplaceURL:= func (m []byte) []byte { cssURL:= string (cssURLPattern.FindSubmatch (m)[1]) srcURL, err:= replaceURL (t, baseURL, cssURL) if err == nil { return []byte («url (» + srcURL.String () + »)») } return m } return cssURLPattern.ReplaceAllFunc (body, cssReplaceURL), nil } Также были отфильтрованы cookie, заголовок X-Frame-Options и выставлен кеш на 24 часа.Web proxy решено было установить на heroku, также подумывал об openshift, но насколько мне известно там ограничение на количество соединений.Решение на heroku + Go меня полностью устроило и нет никаких проблем на квоты никто не жалуется (по сравнению с appengine), с марта месяца как говорится полёт нормальный.
Расширение
Расширение работает хорошо, добавил кнопки zoom. С зумированием была ещё та история, сразу пошёл по неверному пути и применил к iframe CSS transform scale, пришлось каждый раз как изменится зум или главное окно, вычислять размер iframe по новой. Но потом встретилось довольно простое решение:)
zoom:
