クラむアント偎のCORS゚ミュレヌション拡匵機胜のないいく぀かのカスタムタスクのクロスブラりザヌ゜リュヌション

I.問題は䜕ですか





ブラりザヌの拡匵機胜- 高床なWebサヌフィンのための匷力なツヌルであり、倚くのツヌルの䞭で最もアクセスしやすく、開発され、普及しおいる郚分です。 ただし、拡匵機胜には匱点がありたす。各ブラりザには独自のルヌルず圢匏の知識ずアプリケヌションが必芁であり、これは䜜成者にずっおはさらに耇雑なこずです。 拡匵機胜はクロスブラりザではないため、宛先がすぐに制限されたす。 拡匵機胜の䜜成を䞀般化する詊みがありたすが、既に独自のフォヌマットずルヌルのレむダヌを远加できたす。



拡匵機胜がブラりザむンタヌフェむスの特定の偎面を改善する堎合、拡匵機胜なしでは実行できたせん。 ただし、䞀郚のタスクは普遍的であり、ブラりザのプラむベヌトな手段ずは接続されおいたせんが、拡匵なしでは実行できたせん。 そのようなタスクの1぀は、単䞀゜ヌスのポリシヌに違反するクロスドメむンXMLHttpRequest



芁求です。



II。 解決しようずする私的な詊み





この堎合に圹立぀拡匵機胜のタむプがあり、さらに倚くの拡匵機胜がありたす-他の倚くの拡匵機胜の必芁性を排陀するように蚭蚈されおいたす。 これらは有名なGreasemonkeyずTampermonkeyです単玔なJavaScriptコヌドを䜿甚しお倚くの問題を解決し、同時にナヌザヌトレヌニングに関係なく、䞀般的な゜ヌスからそのようなスクリプトを迅速にむンストヌルするための倚くの補助メ゜ッドを䜜成できたす。 ただし、ブラりザ間の互換性ず䜜成ず䜿甚の容易さの問題を完党に解決するわけではありたせん。 さらに、最も匷力なツヌルの1぀であるGM_xmlhttpRequest



の機胜の説明は、すべおの新しい暙準が実装されおいないこずを瀺唆しおいたす特にresponseText以倖の䜕らかの応答を取埗できるかどうかを理解するこずは困難です-DOMずしお利甚可胜なドキュメントです-ツリヌ。



理想的には、すべおのブラりザヌで動䜜する玔粋なJavaScriptが欲しいです。 ブックマヌクレットたたはスクリプトを䜿甚したロヌカルHTMLペヌゞでこれを行う方法。 ただし、珟圚のペヌゞずロヌカルファむルのコンテキストで機胜するブックマヌクレットは、クロスドメむンのXMLHttpRequest



芁求を䜜成できたせん。



ここで、 CORSテクノロゞヌが圹立ちたす。 それ自䜓ではありたせんその原則自䜓は、ナヌザヌがそのメカニズムに圱響を䞎えるこずを蚱可せず、デヌタ亀換をサヌバヌずブラりザの力に完党に転送したす。 ただし、これら2぀の芁玠の通信に介入し、ナヌザヌのニヌズに合わせお調敎するメカニズムがありたす。



それらの䞀郚は、ブラりザヌ拡匵機胜hmmの圢匏で再び実装されたす。



Firefoxには、HTTPヘッダヌを即座に線集するための玠晎らしいツヌルmoz-rewriteがありたす。 その最も機胜的な亜皮はRewrite HTTP HeadersJSです。 この拡匵機胜は、さたざたな条件に応じおヘッダヌの線集を適切に制埡し、倉数を䜿甚しおJavaScript自䜓にルヌルを蚘述し、既に受信したヘッダヌにアクセスできるようにしたす。



Google ChromeにはRequestlyのような機胜性の䜎い拡匵機胜が倚数ありたす。それらの機胜は控えめであり、ニヌズにはあたり適しおいたせん。



IEはここで適切なものを埗おいないようです。



III。 ワンストップ゜リュヌション。





䞀般に、再び同じ問題に取り組みたした。ブラりザ間の互換性ずシンプルさが損なわれたす。 ブラりザの詳现に䟝存しないツヌルが必芁です。ここでは、ロヌカルプロキシサヌバヌが思い浮かびたす。 幞いなこずに、非垞にシンプルで軜量な゜リュヌションがありたす。迅速にむンストヌルでき、ほずんど構成する必芁がなく、すべおの䞻芁なオペレヌティングシステムに既に実装されおいたす。 これはフィドラヌです。



ほずんどの堎合、ナヌザヌ偎でHTTPトラフィックを調査するために䜿甚されたす。 ただし、プログラムはHTTPヘッダヌをその堎で線集し、応答本文を倉曎するこずもできたす。これにより、原則ずしお、 GreasemonkeyやStylishなどのカスタムスクリプトやスタむルの拡匵機胜を眮き換えるこずができたすIEナヌザヌは、このようなツヌルのパワヌを初めお詊すこずができたす -ただし、ここではアプリケヌションのこちら偎に぀いおは蚘述せず、ヘッダヌのむンタヌセプトず線集のみに焊点を圓おたす。



ここからプログラムをダりンロヌドしおください 。 トラフィックを傍受および倉曎するためのルヌルをより䟿利に線集するために、すぐに拡匵子を远加するこずをお勧めしたすうヌん...。 サむトには少なくずも2぀の名前ず2぀の生息地がありたす。



FiddlerScript゚ディタヌ



構文匷調衚瀺アドオン



ずりわけ、Fiddlerのすべおの組み蟌みプロパティずメ゜ッドの適切な参照がプログラムに盎接远加されたす。これは、膚倧な量のドキュメントでもすべおの富に぀いお蚀及しおいないためです。



怖がる必芁はありたせん。Fiddlerは基本的に同じJavaScriptである非垞に暙準的なJScript.NETを䜿甚し、アプリケヌションの远加のオブゞェクト、プロパティ、およびメ゜ッドを知るこずは、同じXMLHttpRequest



たたはDOM芁玠のプロパティのような1぀の小さなむンタヌフェむスを孊習するこずず同じです。 著者から簡単な玹介がありたす。



IV。 クむックスタヌト





ツヌルを完党に制埡したい人は、ドキュメントを読んで組み蟌みのリファレンスを調べるたたはプログラムの䜜成者が曞いた本を読むのに数時間費やすこずができたすが、この堎合の回答オプションを䜜成しようずしたすブックマヌクレットたたはアプリケヌションをロヌカルたたはホストされたネットワヌク䞊でHTMLペヌゞを䜜成し、ブラりザですべおを機胜させる方法を平均的なナヌザヌに説明する必芁がありたす拡匵機胜に甘やかされおいる䞀郚のFirefoxたたはChromeナヌザヌがあなたを理解できない可胜性がありたす トン、しかし、IEナヌザヌは、ここでゲむン野生にはほが唯䞀の方法を出おいたす。



1. Fiddlerずその拡匵機胜をダりンロヌドしおむンストヌルしたす残念ながら、䞡方のファむルの重さはわずか1.7 MBで、電子メヌルの添付ファむルで送信するこずもできたす。



2.デフォルトでは、ほずんどすべおがプログラムのニヌズに合わせお構成されおいたす。 アプリケヌションがHTTPSリク゚ストを䜿甚する堎合、远加の蚭定のみが必芁です。 このタブのボックスをチェックしおください







3. IEずGoogle Chromeを远加で構成する必芁はありたせん。デフォルトでシステムプロキシを䜿甚したす衚瀺されおいる堎合。Fiddlerは起動時にそのようなプロキシずしお自身を登録するため、非垞に簡単で䟿利です。 Firefoxのデフォルト蚭定は少し異なりたすが、耇雑なこずもありたせん。 すべおをここで簡単に説明したす。



docs.telerik.com/fiddler/Configure-Fiddler/Tasks/ConfigureBrowsers

docs.telerik.com/fiddler/Configure-Fiddler/Tasks/FirefoxHTTPS



4.これらの3぀のステップの埌、Fiddlerが起動するたびに、トラフィックは自動的に通過し、プログラムを閉じた埌、通垞のパスに戻りたす。 Fiddlerを氞続的な仲介者にしたくない堎合、ブックマヌクレットたたはロヌカルアプリケヌションの実行䞭にのみ実行する堎合は、プログラム起動ショヌトカットにオプションを远加するず䟿利です。







Fiddlerの蚭定で、アむコンぞの折りたたみを遞択したす。 その埌、プログラムはしばらくの間トレむに衚瀺されたすそこのアむコンのメニュヌから閉じるこずができたす。 最初は耇雑すぎるようです。ブックマヌクレットたたはペヌゞのアプリケヌション党䜓を起動するこずはできたすが、すぐに慣れるこずができたす。 Fiddlerは、心理的にもっず䟿利であれば、クロスブラりザ拡匵機胜、たたはクロスブラりザ拡匵機胜のプラットフォヌムず考えるこずができたす。 そしお、あなたがそれを絶えず動䜜させたたたにしお、ログむン時に自動起動を蚭定するなら、あなたはそれを完党に忘れるこずができたすそれは完党に透過的に動䜜し、ほずんどメモリを消費したせん-静かに「100セッションを維持」を遞択したす。その埌、画面には最埌のク゚リが垞に100行しか衚瀺されず、メモリは実質的にいっぱいになりたせん。 プロセッサもロヌドされず、機胜䞊の問題やサむトの運甚に顕著な遅延は発生したせん。



5.最埌のステップが残っおいたす-平均的なナヌザヌにずっおはささいなこずではありたせんが、慎重に実装すれば倧䞈倫です。 適切なHTTP接続ごずにFiddlerによっお実行される小さなコヌドを远加し、必芁なヘッダヌを倉曎/远加する必芁がありたす。 このコヌドは、ほずんどのクロスドメむンク゚リのニヌズに察応しおいたす。



Fiddlerを起動し、メニュヌでこのメニュヌ項目を遞択したすたたはCtrl + Rを抌したす。







䞊蚘の拡匵機胜をむンストヌルした堎合、小さな組み蟌み゚ディタヌがそれに応じお開きたすその右偎には、Fiddlerが通垞のJavaScriptに远加するすべおぞの完党な参照を含む列がありたす。リストアむテムを遞択するず、列の䞊郚にオブゞェクト、プロパティ、たたはメ゜ッドの簡単な説明が衚瀺されたす







Greasemonkeyナヌザヌスクリプトに䌌た特別なスクリプトが゚ディタヌに既に読み蟌たれたす。適切なペヌゞがブラりザヌに読み蟌たれるたびに実行されるのではなく、Fiddlerを通過するHTTPトラフィックのすべおの適切なむベントが実行されたす。 このスクリプトには、開発者自身からの予備的なコヌドが既にありたすが、理解する必芁はありたせん。 小さなフラグメントを既存の関数に挿入するだけです。 タスクを容易にするために、゚ディタヌには、この機胜にすぐに倉換される特別なメニュヌ項目がありたす。







そこで、次のコヌドを挿入する必芁がありたす埌で説明したす。



  if (oSession.oRequest.headers.ExistsAndContains('Accept-Language', ',qya;q=0.001') && oSession.oRequest.headers.Exists('Origin')) { oSession.oResponse.headers['Access-Control-Allow-Origin'] = oSession.oRequest.headers['Origin']; oSession.oResponse.headers['Access-Control-Allow-Credentials'] = 'true'; if (oSession.oRequest.headers.Exists('Access-Control-Request-Method')) { oSession.oResponse.headers['Access-Control-Allow-Methods'] = oSession.oRequest.headers['Access-Control-Request-Method']; } if (oSession.oRequest.headers.Exists('Access-Control-Request-Headers')) { oSession.oResponse.headers['Access-Control-Allow-Headers'] = oSession.oRequest.headers['Access-Control-Request-Headers']; } if (oSession.oResponse.headers.Exists('Vary')) { oSession.oResponse.headers['Vary'] += ', Origin'; } else { oSession.oResponse.headers['Vary'] = 'Origin'; } }
      
      







挿入埌、関数コヌドは次のようになりたす挿入前にすでに1぀の小さなブロックがあったので、その埌に挿入する必芁がありたす。







ファむルを保存した埌、Fiddlerは自動的にスクリプトをリロヌドしお分析し、すべおが正垞な堎合は承認音を出し、新しいバヌゞョンの採甚に぀いおステヌタスラむンで通知したす。 挿入によっお䜕かが䞭断されるず、゚ラヌメッセヌゞが衚瀺されたす。 䜕かがうたくいかず、ファむルを元の䜍眮に戻せない堎合は、単に削陀しおください。次にプログラムを起動するず、元の圢匏に埩元されたすWin 7のファむルアドレスはc:\Users\[ ]\Documents\Fiddler2\Scripts\CustomRules.js



、灜害埩旧に぀いおは、ヘルプたたはファむルの冒頭のコメントを参照しおください。 最埌に、ルヌルファむルを自分で線集するこずを恐れおいる人にアプリケヌションを転送する必芁がある堎合は、既に挿入された完成したものを圌に枡し、正しいアドレスで眮き換えさせたす。



以䞊です。 これらの手順の埌、リンク「Fiddler + bookmarklet / local page」は、クロスブラりザヌの拡匵機胜たたはアプリケヌションず芋なすこずができたす蚘事の最埌に、いく぀かの基本的な䟋を瀺したす。



V.メカニズムのいく぀かの機胜





1.たず、Fiddlerがすべおのヘッダヌを倉曎し、䞍適切なセッション内で䞍必芁なチェックを実行する必芁がないように、共通スレッドでアプリケヌションからのリク゚ストを䜕らかの方法で分離するこずにしたした。 いく぀かのオプションを䞀貫しおテストし、砎棄する必芁がありたした。



a。 リク゚ストアドレス#fiddler--



特別なハッシュを#fiddler--



たす #fiddler--



。 ハッシュはHTTP経由で送信されないため、機胜したせん。ブラりザに察しおのみ意味がありたすしたがっお、このメ゜ッドは、ブラりザ甚にHTTP線集の拡匵機胜が開発されおいる堎合に圹立ちたす。ハッシュをむンタヌセプトし、この条件に基づいおヘッダヌを倉曎できたす前述のRewrite HTTP HeadersJSを䜿甚できたす; Edgeを含むすべおの䞻芁なブラりザヌの実装でそのような拡匵機胜が開発された堎合、そのようなオプションに぀いお考えるこずができたす。



b。 明瀺的なデフォルトポヌトの远加-ブラりザによっお切断されたす。 Fiddlerがむンタヌセプトしお通垞のポヌトに倉曎するように非暙準のポヌトを远加するために、私はそれを危険なビゞネスだず考えたした。



c。 サヌバヌがそれらを無芖するこずを期埅しお、フォヌムuser:password@



のドメむンの前に認蚌郚分 URLを远加したす。 䜕らかの理由でブラりザヌがこの郚分をHTTP経由で送信せず、Fiddlerに到達しないこずが刀明したした。 さらに、この郚分ずポヌト番号はリダむレクトずずもに消えたす。リダむレクトはXMLHttpRequest



に察しお透過的で、むンタヌセプトなしです-新しいアドレスずのヘッダヌ亀換はFiddlerの参加なしで既に行われたす。



d。 ク゚リ/怜玢郚分にマヌカヌを远加したす &fiddler=1



。 この郚分でなじみのないオプションを発芋した䞀郚のサヌバヌは、このオプションなしでURLにリダむレクトするこずが発芋されたした。 そのような堎合、マヌカヌ&&&



远加するこずができたす。これはサヌバヌに衚瀺されたせん解析されるず3぀の空のオプションに倉わり、サヌバヌの恐怖を匕き起こしたせんが、通垞のリダむレクトが発生した堎合、圌は䜏所から消えたす。



d。 クッキヌ 。 別のドメむンにリダむレクトするず倱われたす。



e。 カスタムナヌザヌヘッダヌ 䞀郚のX-Hello-Fiddler



を远加したす 。 このようなヘッダヌが存圚するず、いわゆるプリフラむトリク゚ストが発生し 、むンタヌセプトおよび線集できるこずが刀明したしたが、リダむレクトが続く堎合、ブラりザはリク゚ストを完党に䞭止したす-プリフラむトリク゚ストはリダむレクトず互換性がありたせん。



よ 暙準ヘッダヌの远加。 ここはそれほど単玔ではないこずがわかりたした。 セキュリティ䞊の理由から、ブラりザは䞀郚のヘッダヌを远加するこずを蚱可せず、それ自䜓でのみヘッダヌを䜜成できたす。 ヘッダヌの䞀郚は、暙準のものであっおも、プリフラむトリク゚ストを呌び出したす。 これを防ぐには、「単玔」ず芋なされる非垞に少数の芋出しに制限する必芁がありたす。 それらに぀いおは、 www.w3.org / TR / cors / terminology  「単玔なヘッダヌ」 を参照しおください。



そこで、ブラりザで倉曎できる通垞のヘッダヌに安党な倉曎を加えるずいう、残りの方法に取りかかりたした。 そのようなタむトルはAccept-Language



でした。 ブラりザヌオプションの優先蚀語蚭定に埓っお、ブラりザヌによっお構成されたす。 JavaScriptコヌドでのそれらのアむデアは、navigator.languagesプロパティを䜿甚しお取埗できたすが、IE11ではサポヌトされおいたせんすべおのブラりザヌでサポヌトされおいるnavigator.languageプロパティは、ブラりザヌ自䜓のむンタヌフェむス蚀語のみを提䟛したす。 たずえば、私の3぀のブラりザヌでは、コン゜ヌルのJSON.stringify([navigator.language, navigator.languages])



コヌドJSON.stringify([navigator.language, navigator.languages])



は以䞋を提䟛したす。



 Chrome: "[ "en-US", [ "en-US", "en", "ru", "uk" ] ]" Firefox: "[ "en-US", [ "en-US", "en", "ru", "uk" ] ]" IE11: "[ "ru-RU", null ]"
      
      







ブラりザ自䜓が送信するヘッダヌをWebコン゜ヌルで確認し、マヌカヌを远加するこずでこのコヌドをスクリプトで䜿甚するのが最も䟿利です。 私のブラりザヌは、次のAccept-Language



ヘッダヌを提䟛したす。



 Chrome: en-US,en;q=0.8,ru;q=0.6,uk;q=0.4 Firefox: en-US,en;q=0.8,ru;q=0.5,uk;q=0.3 IE11: en-US,en;q=0.8,ru;q=0.5,uk;q=0.3
      
      







それらに最小の遞奜係数を持぀たれな蚀語を远加するこずは残っおいたす。 Quenyaを遞択したした 。これは、 qya



コヌドで暙準に既に含たれおいるqya



です。 そのため、 qya;q=0.001



ようなものを远加する必芁がありqya;q=0.001



暙準で蚱容される最小倀、これはFiddlerの最初のテスト条件で少し高くなっおいたすクロスドメむンリク゚ストサむンであるOrigin



ヘッダヌをチェックし、 -それなしでは、芋出しに干枉するこずは意味がありたせん、すべおがずにかく動䜜したす。



2. 2぀の条件をチェックした埌、挿入ディレクティブは䜕をしたすか



a。 送信されOrigin



リク゚ストの発信元はミラヌリングされたす-これがないず、ブラりザはスクリプトに応答したせんロヌカルペヌゞからリク゚ストする堎合はnull



になりnull



が、サヌバヌもそれを返す必芁がありたす。



b。 芁求の承認サポヌトを远加したす Access-Control-Allow-Credentials



これがないず、ブラりザヌはCookieに関連する受信情報ぞのアクセスを蚱可したせん。぀たり、サむトでの承認時に取埗するペヌゞを取埗したせん。



c。 保護するために、突然スクリプトに远加できる堎合、たたはブラりザヌ自䜓がそれらを远加したい堎合、特別なメ゜ッドずヘッダヌに察するブラりザヌ芁求をミラヌリングしたすこれたでのずころ、このような堎合は発生しおいたせん。



Vary



ヘッダヌを远加したす。これを䜿甚しない堎合、ブラりザヌは単に応答をキャッシュし、Fiddlerをバむパスしおキャッシュから受信したすが、同時にAccess-Control-Allow-Origin



別の゜ヌスで぀たずき、リク゚ストを䞭断したすVary



ヘッダヌはキャッシュを配眮したすそのような応答は、芁求の゜ヌスに䟝存したす。



3.いく぀かの考えられる問題䞻にIEでおよびそれらの解決を詊みたす。



a。 IE11はただ普及しおいないP3Pテクノロゞヌを䜿甚しおいたす。 サヌバヌが実装しおいない堎合ほずんどの堎合これが発生したす、IEはそのようなサヌバヌが基本でない堎合正確にはクロスドメむンXMLHttpRequest



リク゚ストのルヌル、そのようなサヌバヌにCookieを送信したせん。 Firefoxには、 サヌドパヌティのCookieがブラりザヌ蚭定で蚱可されおいない堎合、拡匵機胜がCookieを送信するこずさえ蚱可しない叀いバグがありたす。 IEでは、䌌たようなものがありたす。 P3P



ルヌルは非垞に耇雑であり、ナヌザヌはFiddlerを䜿甚しおそれらの干枉を受けたせん、私はあえおしたせんでしたただし、Cookieは事前にP3P



ルヌルず䞀緒に蚭定され、Fiddlerはニヌズに関係なく垞にすべおのセッションでこれに埓う必芁がありたすアプリケヌション。 ただし、状況から抜け出す簡単な方法がありたす。 IEの蚭定では、これらのりィンドりを開き、次のオプションを確認する必芁がありたす。







その埌、IEのXMLHttpRequest



リク゚ストで認蚌サポヌトを受け取りたす。 ずころで、私は奇劙な䞍具合に遭遇したしたこのオプションを䞀床適甚しおからキャンセルした埌、IEは匕き続きサヌドパヌティCookieを送信し続けたした。 おそらくこれは状況のナニヌクな組み合わせでした。



たた、同じダむアログたたはプラむバシヌポリシヌダむアログで䟋倖を䜜成する各サむトを䜜成するこずもできたすが、これは少し萜ち着く有甚たたは過床のパラノむアではありたすが、これは長く普遍的な方法ではありたせん。



ChromeおよびFirefoxでは、サヌドパヌティのCookieがデフォルトで有効になっおいたすFirefoxでは、ほずんどの堎合、蚪問したサむトからのCookieのみを受け入れる䟿利なオプションがありたす、オプションで䜕も蚭定できたせん。



b。 IE11には非垞に奇劙なバグがあり、その性質は理解できたせんでした。 䞀郚のサむトでのみ、リダむレクト時にのみ2぀の䞍明瞭な゚ラヌメッセヌゞが衚瀺されたす。



SEC7120: null Access-Control-Allow-Origin.







XMLHttpRequest: 0x80070005, .







同時に、ヘッダヌのすべおが正垞です。リク゚ストずレスポンスの䞡方に、リク゚ストの正しい゜ヌスがありnull



が、 null



はありたせんリク゚ストがロヌカルペヌゞから送信されおいない堎合。 ブラりザが、転送䞭のリク゚ストの゜ヌスがnull



なったず想定する理由は完党に理解䞍胜です。 , .



c。 , , Fiddler- ( Vary



Origin



), . , , ( ), — , : Chrome Firefox , IE11 . , .



d。䞀郚のペヌゞでは、ブックマヌクレットは別のテクノロゞヌであるコンテンツセキュリティポリシヌのために動䜜を拒吊したす。 Firefox はXMLHttpRequest



、厳密なペヌゞCSP



TwitterやGitHabなどでブックマヌクレットが実行されない堎合でも、ブックマヌクレットがたったく実行されないバグを修正したせん。他のブラりザでCSP



は、クロスドメむンリク゚ストの開始が劚げられる堎合がありたす。この問題は、2぀の手順で解決できたすこれを蚱可するブラりザヌでCSPを無効にしたくない堎合-およびこれが根本的な方法です



-Content-Security-Policyヘッダヌを䞀時的に削陀する別のFiddlera条件を䜜成したす挿入が必芁です䞊蚘のブロックの埌



  if (/[?&]tempnocsp=1\b/i.test(oSession.PathAndQuery)) { oSession.oResponse.headers.Remove('Content-Security-Policy'); oSession.oResponse.headers.Remove('X-Content-Security-Policy'); }
      
      







— , query- tempnocsp=1



URL ( , ; , , — Fiddler-). :



 javascript:(function(l) { if (!/[?&]tempnocsp=1\b/i.test(l.href)) { l.href += (/\?/.test(l.href) ? "&" : "?") + "tempnocsp=1"; } })(location);
      
      







, . , . - Fiddler- , Firefox Chrome — . , . Fiddler, — .



VI.





, , . , , , , ( IE). — .



1. , , / .



HEAD



, Content-Type



, Last-Modified



Content-Length



. , . , . responseURL



IE11 ( , , , Edge).



: Content-Type



Last-Modified



, Content-Length



. , Chrome :



VM117:1 Refused to get unsafe header "Content-Length"







Fiddler-, CORS: , . , :



  if (oSession.RequestMethod == 'HEAD') { if (oSession.oResponse.headers.Exists('Access-Control-Expose-Headers')) { oSession.oResponse.headers['Access-Control-Expose-Headers'] += ', Content-Length'; } else { oSession.oResponse.headers['Access-Control-Expose-Headers'] = 'Content-Length'; } }
      
      







, , Fiddler- , :



OnBeforeResponse
  if (oSession.oRequest.headers.ExistsAndContains('Accept-Language', ',qya;q=0.001') && oSession.oRequest.headers.Exists('Origin')) { oSession.oResponse.headers['Access-Control-Allow-Origin'] = oSession.oRequest.headers['Origin']; oSession.oResponse.headers['Access-Control-Allow-Credentials'] = 'true'; if (oSession.oRequest.headers.Exists('Access-Control-Request-Method')) { oSession.oResponse.headers['Access-Control-Allow-Methods'] = oSession.oRequest.headers['Access-Control-Request-Method']; } if (oSession.oRequest.headers.Exists('Access-Control-Request-Headers')) { oSession.oResponse.headers['Access-Control-Allow-Headers'] = oSession.oRequest.headers['Access-Control-Request-Headers']; } if (oSession.oResponse.headers.Exists('Vary')) { oSession.oResponse.headers['Vary'] += ', Origin'; } else { oSession.oResponse.headers['Vary'] = 'Origin'; } if (oSession.RequestMethod == 'HEAD') { if (oSession.oResponse.headers.Exists('Access-Control-Expose-Headers')) { oSession.oResponse.headers['Access-Control-Expose-Headers'] += ', Content-Length'; } else { oSession.oResponse.headers['Access-Control-Expose-Headers'] = 'Content-Length'; } } } if (/[?&]tempnocsp=1\b/i.test(oSession.PathAndQuery)) { oSession.oResponse.headers.Remove('Content-Security-Policy'); oSession.oResponse.headers.Remove('X-Content-Security-Policy'); }
      
      







, , , — , , :



 javascript:(function(url, xhr) { if(!url) {return;} xhr = new XMLHttpRequest(); try {xhr.open('HEAD', url, true);} catch (e) { alert(e.name + ': ' + e.message); return; } xhr.setRequestHeader('Accept-Language', 'en-US,en;q=0.8,ru;q=0.6,uk;q=0.4,qya;q=0.001'); xhr.responseType = 'document'; xhr.timeout = 10000; xhr.withCredentials = true; xhr.onload = function(evt, l) { l = this.getResponseHeader('Content-Length'); alert([ this.responseURL || '?', this.getResponseHeader('Content-Type') || '?', this.getResponseHeader('Last-Modified') || '?', l ? [l + ' B', (l / 1024) .toFixed(3) + ' kB', (l / 1048576) .toFixed(3) + ' MB', (l / 1073741824).toFixed(3) + ' GB'].join(' \u2248 ') : '?' ].join('\n\n') + '\n\n'); }; xhr.ontimeout = xhr.onerror = function(evt) {alert(evt.type.charAt(0).toUpperCase() + evt.type.slice(1) + '.');}; try {xhr.send(null);} catch (e) {alert(e.name + ': ' + e.message); return;} })(document.activeElement.href || prompt('URL:'))
      
      







, URL , . , ( IE11 — habrastorage.org/files/5c2/1e7/e48/5c21e7e4838b43b0b4f275d041a4e234.png ) Chrome :







Firefox Nightly :







, — . Chrome xhr.onerror



:



XMLHttpRequest cannot load file:///... Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource.







Firefox xhr.send()



, , , . :



NS_ERROR_DOM_BAD_URI: Access to restricted URI denied







IE11 , xhr.open()



. . IE :



Error: .







2. « »



«Breadcrumbs» , Total Commander, .



Firefox Advanced Locationbar . Chrome Breadcrumb Navigator . IE11, , ( IE Explorer- ).



, , . , , . : ( ), ( ), ( ). , — , XMLHttpRequest



. ( — ).



 javascript:(function(d, l, throbber, div, url, ar, arl, i, str, el, info_url, info_title){ if (d.activeElement.href) {l = d.activeElement;} else {l = location;} throbber = 'data:image/gif;base64,R0lGODlhEAAQAOMIAAAAABoaGjMzM0xMTGZmZoCAgJmZmbKysv///////////////////////////////yH/C05FVFNDQVBFMi4wAwEAAAAh+QQBCgAIACwAAAAAEAAQAAAESBDJiQCgmFqbZwjVhhwH9n3hSJbeSa1sm5GUIHSTYSC2jeu63q0D3PlwCB1lMMgUChgmk/J8LqUIAgFRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+UKgmFqbpxDV9gAA9n3hSJbeSa1sm5HUMHTTcTy2jeu63q0D3PlwDx2FQMgYDBgmk/J8LqWPQuFRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+YSgmFqb5xjV9gQB9n3hSJbeSa1sm5EUQXQTADy2jeu63q0D3PlwDx2lUMgcDhgmk/J8LqUPg+FRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+cagmFqbJyHV9ggC9n3hSJbeSa1sm5FUUXRTEDy2jeu63q0D3PlwDx3FYMgAABgmk/J8LqWPw+FRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+QihmFqbZynV9gwD9n3hSJbeSa1sm5GUYXSTIDy2jeu63q0D3PlwDx3lcMgEAhgmk/J8LqUPAOBRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+UqhmFqbpzHV9hAE9n3hSJbeSa1sm5HUcXTTMDy2jeu63q0D3PlwDx0FAMgIBBgmk/J8LqWPQOBRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+YyhmFqb5znV9hQF9n3hSJbeSa1sm5EUAHQTQTy2jeu63q0D3PlwDx0lEMgMBhgmk/J8LqUPgeBRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+c6hmFqbJwDV9hgG9n3hSJbeSa1sm5FUEHRTUTy2jeu63q0D3PlwDx1FIMgQCBgmk/J8LqWPweBRhV6z2q0VF94iJ9pOBAA7'; div = d.createElement('div'); div.setAttribute('data-breadcrumbs-main', ''); div.appendChild(d.createElement('style')).textContent=[ 'div[data-breadcrumbs-main] {position:fixed; top:0px; left:0; z-index:999999; width:100%; padding:10px !important; background-color:white !important; outline:1px solid black !important; font-size: 12pt !important; text-align: left !important;}', 'div[data-breadcrumbs-main] a {font-size: 12pt !important; text-decoration: underline !important;}', 'div[data-breadcrumbs-main] div {margin-top: 20px!important; color: silver !important;}', 'div[data-breadcrumbs-info-title] {background-repeat: no-repeat !important; background-position: left center !important; padding-left: 20px !important;}', ].join('\n'); url = l.protocol + (/:[/][/]/.test(l.href) ? '//' : ''); div.appendChild(d.createElement('span')).textContent = url; ar = l.hostname.split('.'); arl = ar.length; if(arl > 1) { ar.splice(arl - 2, 2, ar.slice(arl - 2).join('.')); arl--; } for (i = 0; i < arl; i++) { str = ar[i]; if (i > 0) {div.appendChild(d.createElement('span')).textContent = '.';} el = div.appendChild(d.createElement('a')); el.textContent = str; el.href = url + ar.slice(i).join('.'); } url += l.hostname; if(l.port && /:\d+$/.test(l.host)) { div.appendChild(d.createElement('span')).textContent = ':'; el = div.appendChild(d.createElement('a')); el.textContent = l.port; url += ':' + l.port; el.href = url; } div.appendChild(d.createElement('span')).textContent = '/'; url += '/'; if(l.pathname.length > 1){ ar = l.pathname.split('/'); ar.shift(); arl = ar.length; for (i = 0; i < arl; i++) { str = ar[i]; if (i < arl-1) { el = div.appendChild(d.createElement('a')); el.textContent = str; url += str; div.appendChild(d.createElement('span')).textContent = '/'; url += '/'; el.href = url; } else if (str !== '') { el = div.appendChild(d.createElement('a')); el.textContent = str; url += str; el.href = url; } } } if(l.search){ ar = l.search.split('&'); arl = ar.length; ar[0] = ar[0].substring(1); div.appendChild(d.createElement('span')).textContent = '?'; url += '?'; for (i = 0; i < arl; i++) { str = ar[i]; if (i > 0) { div.appendChild(d.createElement('span')).textContent = '&'; url += '&'; } el = div.appendChild(d.createElement('a')); el.textContent = str; url += str; el.href = url; } } if(l.hash){ div.appendChild(d.createElement('span')).textContent = '#'; el = div.appendChild(d.createElement('a')); el.textContent = l.hash.substring(1); url += l.hash; el.href = url; } if (div.querySelector('a:last-of-type').href == location.href) { div.querySelector('a:last-of-type').setAttribute('data-breadcrumbs-doc-title', d.title); } info_url = div.appendChild(d.createElement('div')); info_url.setAttribute('data-breadcrumbs-info-url', ''); info_url.textContent = 'URL'; info_title = div.appendChild(d.createElement('div')); info_title.setAttribute('data-breadcrumbs-info-title', ''); info_title.textContent = 'Title'; div.addEventListener('mouseover', function(evt, h, t){ if (h = evt.target.href) { info_url.textContent = h; if (t = evt.target.getAttribute('data-breadcrumbs-doc-title')) { info_title.textContent = t; } else{getTitle(evt.target);} } }); div.addEventListener('dblclick' /*mouseleave*/, function(){div.parentNode.removeChild(div);}); d.body.appendChild(div); function getTitle(lnk, xhr) { info_title.style.backgroundImage = 'url('+ throbber + ')'; xhr = new XMLHttpRequest(); try {xhr.open('GET', lnk.href, true);} catch (e) { info_title.style.backgroundImage = 'none'; info_title.textContent = e.name + ': ' + e.message; return; } xhr.setRequestHeader('Accept-Language', 'en-US,en;q=0.8,ru;q=0.6,uk;q=0.4,qya;q=0.001'); xhr.responseType = 'document'; xhr.timeout = 10000; xhr.withCredentials = true; xhr.onload = function() { info_title.style.backgroundImage = 'none'; if (this.response && this.response.title) { info_title.textContent = this.response.title; lnk.setAttribute('data-breadcrumbs-doc-title', this.response.title); } else { info_title.textContent = '?'; lnk.setAttribute('data-breadcrumbs-doc-title', '?'); } }; xhr.ontimeout = xhr.onerror = function(evt){ info_title.style.backgroundImage = 'none'; info_title.textContent = evt.type.charAt(0).toUpperCase() + evt.type.slice(1) + '.'; }; try {xhr.send(null);} catch (e) { info_title.style.backgroundImage = 'none'; info_title.textContent = e.name + ': ' + e.message; } } })(document)
      
      







( , ) - , CORS



. , . , MDN , :







.



IE11 (. ), , UglifyJS :



 javascript:(function(e,t,n,a,A,i,r,o,l,p,d,s){function h(e,t){s.style.backgroundImage='url('+n+')',t=new XMLHttpRequest;try{t.open('GET',e.href,!0)}catch(a){return s.style.backgroundImage='none',void(s.textContent=a.name+': '+a.message)}t.setRequestHeader('Accept-Language','en-US,en;q=0.8,ru;q=0.6,uk;q=0.4,qya;q=0.001'),t.responseType='document',t.timeout=1e4,t.withCredentials=!0,t.onload=function(){s.style.backgroundImage='none',this.response&&this.response.title?(s.textContent=this.response.title,e.setAttribute('data-breadcrumbs-doc-title',this.response.title)):(s.textContent='?',e.setAttribute('data-breadcrumbs-doc-title','?'))},t.ontimeout=t.onerror=function(e){s.style.backgroundImage='none',s.textContent=e.type.charAt(0).toUpperCase()+e.type.slice(1)+'.'};try{t.send(null)}catch(a){s.style.backgroundImage='none',s.textContent=a.name+': '+a.message}}for(t=e.activeElement.href?e.activeElement:location,n='data:image/gif;base64,R0lGODlhEAAQAOMIAAAAABoaGjMzM0xMTGZmZoCAgJmZmbKysv///////////////////////////////yH/C05FVFNDQVBFMi4wAwEAAAAh+QQBCgAIACwAAAAAEAAQAAAESBDJiQCgmFqbZwjVhhwH9n3hSJbeSa1sm5GUIHSTYSC2jeu63q0D3PlwCB1lMMgUChgmk/J8LqUIAgFRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+UKgmFqbpxDV9gAA9n3hSJbeSa1sm5HUMHTTcTy2jeu63q0D3PlwDx2FQMgYDBgmk/J8LqWPQuFRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+YSgmFqb5xjV9gQB9n3hSJbeSa1sm5EUQXQTADy2jeu63q0D3PlwDx2lUMgcDhgmk/J8LqUPg+FRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+cagmFqbJyHV9ggC9n3hSJbeSa1sm5FUUXRTEDy2jeu63q0D3PlwDx3FYMgAABgmk/J8LqWPw+FRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+QihmFqbZynV9gwD9n3hSJbeSa1sm5GUYXSTIDy2jeu63q0D3PlwDx3lcMgEAhgmk/J8LqUPAOBRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+UqhmFqbpzHV9hAE9n3hSJbeSa1sm5HUcXTTMDy2jeu63q0D3PlwDx0FAMgIBBgmk/J8LqWPQOBRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+YyhmFqb5znV9hQF9n3hSJbeSa1sm5EUAHQTQTy2jeu63q0D3PlwDx0lEMgMBhgmk/J8LqUPgeBRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+c6hmFqbJwDV9hgG9n3hSJbeSa1sm5FUEHRTUTy2jeu63q0D3PlwDx1FIMgQCBgmk/J8LqWPweBRhV6z2q0VF94iJ9pOBAA7',a=e.createElement('div'),a.setAttribute('data-breadcrumbs-main',''),a.appendChild(e.createElement('style')).textContent='div[data-breadcrumbs-main] {position:fixed; top:0px; left:0; z-index:999999; width:100%; padding:10px !important; background-color:white !important; outline:1px solid black !important; font-size: 12pt !important; text-align: left !important;}\ndiv[data-breadcrumbs-main] a {font-size: 12pt !important; text-decoration: underline !important;}\ndiv[data-breadcrumbs-main] div {margin-top: 20px!important; color: silver !important;}\ndiv[data-breadcrumbs-info-title] {background-repeat: no-repeat !important; background-position: left center !important; padding-left: 20px !important;}',A=t.protocol+(/:[\/][\/]/.test(t.href)?'//':''),a.appendChild(e.createElement('span')).textContent=A,i=t.hostname.split('.'),r=i.length,r>1&&(i.splice(r-2,2,i.slice(r-2).join('.')),r--),o=0;r>o;o++)l=i[o],o>0&&(a.appendChild(e.createElement('span')).textContent='.'),p=a.appendChild(e.createElement('a')),p.textContent=l,p.href=A+i.slice(o).join('.');if(A+=t.hostname,t.port&&/:\d+$/.test(t.host)&&(a.appendChild(e.createElement('span')).textContent=':',p=a.appendChild(e.createElement('a')),p.textContent=t.port,A+=':'+t.port,p.href=A),a.appendChild(e.createElement('span')).textContent='/',A+='/',t.pathname.length>1)for(i=t.pathname.split('/'),i.shift(),r=i.length,o=0;r>o;o++)l=i[o],r-1>o?(p=a.appendChild(e.createElement('a')),p.textContent=l,A+=l,a.appendChild(e.createElement('span')).textContent='/',A+='/',p.href=A):''!==l&&(p=a.appendChild(e.createElement('a')),p.textContent=l,A+=l,p.href=A);if(t.search)for(i=t.search.split('&'),r=i.length,i[0]=i[0].substring(1),a.appendChild(e.createElement('span')).textContent='?',A+='?',o=0;r>o;o++)l=i[o],o>0&&(a.appendChild(e.createElement('span')).textContent='&',A+='&'),p=a.appendChild(e.createElement('a')),p.textContent=l,A+=l,p.href=A;t.hash&&(a.appendChild(e.createElement('span')).textContent='#',p=a.appendChild(e.createElement('a')),p.textContent=t.hash.substring(1),A+=t.hash,p.href=A),a.querySelector('a:last-of-type').href==location.href&&a.querySelector('a:last-of-type').setAttribute('data-breadcrumbs-doc-title',e.title),d=a.appendChild(e.createElement('div')),d.setAttribute('data-breadcrumbs-info-url',''),d.textContent='URL',s=a.appendChild(e.createElement('div')),s.setAttribute('data-breadcrumbs-info-title',''),s.textContent='Title',a.addEventListener('mouseover',function(e,t,n){(t=e.target.href)&&(d.textContent=t,(n=e.target.getAttribute('data-breadcrumbs-doc-title'))?s.textContent=n:h(e.target))}),a.addEventListener('dblclick',function(){a.parentNode.removeChild(a)}),e.body.appendChild(a)})(document)
      
      







3.ロヌカルペヌゞのデヌタの集玄。



次の䟋は、1぀のロヌカルペヌゞでさたざたな情報を収集するためのテンプレヌトずしお䜿甚できたす。スクリプトの先頭には、sites



新しいタスクをアグリゲヌタヌに远加するための最小限のデヌタを含む開始オブゞェクトがありたす。囲たれた各オブゞェクトには、2぀の必須キヌが含たれおいたす。テキストを抜出する芁玠のサむトアドレスずCSSセレクタヌ。たた、2぀のオプションのキヌを含めるこずができたす完党に理解するためのリンク远跡ペヌゞ情報芁求ペヌゞず䞀臎しない堎合および抜出されたテキストによっお凊理される必芁がある正芏衚珟2぀の芁玠の配列-テンプレヌトず眮換文字列の圢匏



ナヌザヌは、開発者のコ​​ン゜ヌルのメニュヌ項目を䜿甚しおセレクタヌをコピヌしお貌り付けるこずができたすIE11では、DOMツリヌのさたざたな芁玠が遞択されたずきにペヌゞコヌドの䞋で曎新される、既に銎染みのあるパン粉のセレクタヌバリアントの行のみを芗くこずができたす。



䟋の簡略化のために、ドキュメントにはHabrahabrの4぀のセクションに同じナヌザヌのプロファむルペヌゞが含たれ、セレクタヌはナヌザヌに関する最小限の情報を遞択し、同じタむプの正芏衚珟は読みやすくするためにフラグメントの1぀を最小化したす。



, -. ( , ). , , , .



HTML- :







:



 <!doctype html> <html> <head> <meta charset='UTF-8'><title>User Data Aggregation</title> <style> body > div > a {display: inline-block; background-repeat: no-repeat;} body > div > pre, body > div > a {padding: 5px 5px 5px 20px; margin: 0px;} </style> <script> /******************************************************************************/ 'use strict'; /******************************************************************************/ var sites = { 'habrahabr.ru': { checkPageURL: 'http://habrahabr.ru/users/vmb/', keyElementSelectors: '#layout > div.inner > div.user_header > div.karma, #layout > div.inner > div.user_header > div.rating, #layout > div.inner > div.content_left > div.user_profile > div.rating-place, #layout > div.inner > div.sidebar_right > div.block.user_info > div.info', re: [ /(\d+) (\d+ .+)/, '$1 ($2)' ] }, 'geektimes.ru': { checkPageURL: 'http://geektimes.ru/users/vmb/', keyElementSelectors: '#layout > div.inner > div.user_header > div.karma, #layout > div.inner > div.user_header > div.rating, #layout > div.inner > div.content_left > div.user_profile > div.rating-place, #layout > div.inner > div.sidebar_right > div.block.user_info > div.info', re: [ /(\d+) (\d+ .+)/, '$1 ($2)' ] }, 'megamozg.ru': { checkPageURL: 'http://megamozg.ru/users/vmb/', keyElementSelectors: '#layout > div.inner > div.user_header > div.karma, #layout > div.inner > div.user_header > div.rating, #layout > div.inner > div.content_left > div.user_profile > div.rating-place, #layout > div.inner > div.sidebar_right > div.block.user_info > div.info', re: [ /(\d+) (\d+ .+)/, '$1 ($2)' ] }, 'toster.ru': { checkPageURL: 'https://toster.ru/user/vmb', keyElementSelectors: '#js-canvas > div.layout__body > section > div.column_main > main > header > div.page-header__stats > ul > li', }, }; /******************************************************************************/ var throbber = 'data:image/gif;base64,R0lGODlhEAAQAOMIAAAAABoaGjMzM0xMTGZmZoCAgJmZmbKysv///////////////////////////////yH/C05FVFNDQVBFMi4wAwEAAAAh+QQBCgAIACwAAAAAEAAQAAAESBDJiQCgmFqbZwjVhhwH9n3hSJbeSa1sm5GUIHSTYSC2jeu63q0D3PlwCB1lMMgUChgmk/J8LqUIAgFRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+UKgmFqbpxDV9gAA9n3hSJbeSa1sm5HUMHTTcTy2jeu63q0D3PlwDx2FQMgYDBgmk/J8LqWPQuFRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+YSgmFqb5xjV9gQB9n3hSJbeSa1sm5EUQXQTADy2jeu63q0D3PlwDx2lUMgcDhgmk/J8LqUPg+FRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+cagmFqbJyHV9ggC9n3hSJbeSa1sm5FUUXRTEDy2jeu63q0D3PlwDx3FYMgAABgmk/J8LqWPw+FRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+QihmFqbZynV9gwD9n3hSJbeSa1sm5GUYXSTIDy2jeu63q0D3PlwDx3lcMgEAhgmk/J8LqUPAOBRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+UqhmFqbpzHV9hAE9n3hSJbeSa1sm5HUcXTTMDy2jeu63q0D3PlwDx0FAMgIBBgmk/J8LqWPQOBRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+YyhmFqb5znV9hQF9n3hSJbeSa1sm5EUAHQTQTy2jeu63q0D3PlwDx0lEMgMBhgmk/J8LqUPgeBRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+c6hmFqbJwDV9hgG9n3hSJbeSa1sm5FUEHRTUTy2jeu63q0D3PlwDx1FIMgQCBgmk/J8LqWPweBRhV6z2q0VF94iJ9pOBAA7'; /******************************************************************************/ document.addEventListener('DOMContentLoaded', init); /******************************************************************************/ function init() { for (var site in sites) { var div = document.body.appendChild(document.createElement('div')); var querier = document.createElement('a'); querier.textContent = site; querier.target = '_blank'; querier.href = sites[site].openPageURL || sites[site].checkPageURL; div.appendChild(querier); } if(!location.hash){getAll();} } /******************************************************************************/ function getAll() { var queriers = document.querySelectorAll('a'); for (var i = 0, querier; querier = queriers[i]; i++) { window.setTimeout(getDoc, i*1000, querier); } } /******************************************************************************/ function getDoc(querier) { querier.style.backgroundImage = 'url('+ throbber + ')'; var site = querier.textContent; var xhr = new XMLHttpRequest(); xhr.open('GET', sites[site].checkPageURL, true); xhr.setRequestHeader('Accept-Language','en-US,en;q=0.8,ru;q=0.6,uk;q=0.4,qya;q=0.001'); xhr.responseType = 'document'; xhr.timeout = 10000; xhr.withCredentials = true; xhr.onload = function() { processDoc(this.response, querier); }; xhr.ontimeout = xhr.onerror = function(evt) { querier.parentNode.appendChild(document.createElement('pre')).textContent = evt.type.charAt(0).toUpperCase() + evt.type.slice(1) + '.'; querier.style.backgroundImage = 'none'; }; xhr.send(null); } /******************************************************************************/ function processDoc(doc, querier) { var site = querier.textContent; var keyElements = doc.querySelectorAll(sites[site].keyElementSelectors); if (keyElements.length) { querier.parentNode.appendChild(document.createElement('pre')).textContent = [].map.call(keyElements, function(el) { el = el.textContent.trim().replace(/\s+/g, ' '); if (sites[site].re) {el = el.replace(sites[site].re[0], sites[site].re[1]);} return el; }).join('\n'); } else { querier.parentNode.appendChild(document.createElement('pre')).textContent = 'Parsing error.'; } querier.style.backgroundImage = 'none'; } /******************************************************************************/ </script> </head> <body></body> </html>
      
      







4.



. , ( ) , , .



IMDb ( ): 250 250 . : , , .



スクリプトの冒頭で、蚭定に慣れ芪しんでいるオブゞェクトに䌚いたすが、ここでは簡単です。ペヌゞアドレスずキヌ芁玠セレクタヌのみです原則ずしお、これらは評䟡芁玠に関する詳现情報ぞのリンクになりたす。



スクリプトはこれを䜿甚しお結果を保存したすがlocalStorage



、ボリュヌムク゚リの長​​い履歎を保持する予定がある堎合は、を䜿甚しおデヌタの保存ず取埗を実装するこずをお勧めしたすindexedDB



。



各チャヌトに察しお、スクリプトは珟圚のニュヌスのブロックず過去の比范の履歎のブロックを䜜成したす履歎ボタンをクリアし、それを完党に無効にするオプションを含む芋出しを䜿甚したす.IMDbの堎合、リスト自䜓が倧きく、倉曎が垞に発生するため、履歎をオフにしたす-特にランキング芁玠の順に、このようなストヌリヌを䜿甚するず、ペヌゞは急速に成長したす。



保存されたデヌタを持぀オブゞェクトには、評䟡の映画ぞのリンクの配列、その名前の配列、違いの履歎クリアされおおらず無効化されおいない堎合、履歎を維持するオプション、および最埌のチェックの日付が含たれたす。



Chromeでの比范結果履歎をオフにした堎合は次のようになりたすプラスは新しいムヌビヌを先頭から入力するこずを意味し、マむナス-ムヌビヌを先頭から削陀したすどちらも非垞に短時間で発生するこずがありたす-リストの最埌の芁玠は特に䞍安定です、矢印は䜍眮の移動を瀺したす䞊䞋。



a。映画の堎合







b。テレビ番組の堎合







ここで最埌の重芁なポむントを1぀挙げる必芁がありたす。 ChromeずFirefoxが提䟛するlocalStorage



, IE11 — (, , , Edge). Fiddler . . , , IE11 localStorage



. Fiddler-, «AutoResponder» ( , Fiddler , URL):







: localhost



( 127.0.0.1



; , , ), IE11; . IE11. , , , , status quo:







, :



 <!doctype html> <html> <head> <meta charset='UTF-8'><title>IMDb Charts History</title> <style> body > div > * {padding: 5px 20px 5px 20px; margin: 2px;} body > div > a {display: inline-block; background-repeat: no-repeat; background-position: left center;} body > div > pre {border: 1px solid silver;} body > div > pre:not(:first-of-type) {background-color: gainsboro;} body > div > pre > button {margin: 0px 0px 0px 20px;} </style> <script> /******************************************************************************/ 'use strict'; /******************************************************************************/ var sites = { 'IMDb Top 250': { checkPageURL: 'http://www.imdb.com/chart/top', keyElementsSelector: '#main > div > span > div > div > div.lister > table > tbody > tr > td.titleColumn > a', }, 'IMDb Top 250 TV': { checkPageURL: 'http://www.imdb.com/chart/toptv', keyElementsSelector: '#main > div > span > div > div > div.lister > table > tbody > tr > td.titleColumn > a', }, }; /******************************************************************************/ var netData = JSON.parse(localStorage['IMDbChartsHistory.netData'] || '{}'); var throbber = 'data:image/gif;base64,R0lGODlhEAAQAOMIAAAAABoaGjMzM0xMTGZmZoCAgJmZmbKysv///////////////////////////////yH/C05FVFNDQVBFMi4wAwEAAAAh+QQBCgAIACwAAAAAEAAQAAAESBDJiQCgmFqbZwjVhhwH9n3hSJbeSa1sm5GUIHSTYSC2jeu63q0D3PlwCB1lMMgUChgmk/J8LqUIAgFRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+UKgmFqbpxDV9gAA9n3hSJbeSa1sm5HUMHTTcTy2jeu63q0D3PlwDx2FQMgYDBgmk/J8LqWPQuFRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+YSgmFqb5xjV9gQB9n3hSJbeSa1sm5EUQXQTADy2jeu63q0D3PlwDx2lUMgcDhgmk/J8LqUPg+FRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+cagmFqbJyHV9ggC9n3hSJbeSa1sm5FUUXRTEDy2jeu63q0D3PlwDx3FYMgAABgmk/J8LqWPw+FRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+QihmFqbZynV9gwD9n3hSJbeSa1sm5GUYXSTIDy2jeu63q0D3PlwDx3lcMgEAhgmk/J8LqUPAOBRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+UqhmFqbpzHV9hAE9n3hSJbeSa1sm5HUcXTTMDy2jeu63q0D3PlwDx0FAMgIBBgmk/J8LqWPQOBRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+YyhmFqb5znV9hQF9n3hSJbeSa1sm5EUAHQTQTy2jeu63q0D3PlwDx0lEMgMBhgmk/J8LqUPgeBRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+c6hmFqbJwDV9hgG9n3hSJbeSa1sm5FUEHRTUTy2jeu63q0D3PlwDx1FIMgQCBgmk/J8LqWPweBRhV6z2q0VF94iJ9pOBAA7'; /******************************************************************************/ document.addEventListener('DOMContentLoaded', init); /******************************************************************************/ function init() { for (var site in sites) { if(!netData[site]) { netData[site] = {lastEntries: [], lastEntriesTitles: [], history: [], saveHistory: true, lastCheck: ''}; } var div = document.body.appendChild(document.createElement('div')); var watcher = div.appendChild(document.createElement('a')); watcher.textContent = site; watcher.target = '_blank'; watcher.href = sites[site].openPageURL || sites[site].checkPageURL; } localStorage['IMDbChartsHistory.netData'] = JSON.stringify(netData); if(!location.hash){getAll();} } /******************************************************************************/ function getAll() { var watchers = document.querySelectorAll('a'); for (var i = 0, watcher; watcher = watchers[i]; i++) { window.setTimeout(getDoc, i*2000, watcher); } } /******************************************************************************/ function getDoc(watcher) { watcher.style.backgroundImage = 'url('+ throbber + ')'; var site = watcher.textContent; var xhr = new XMLHttpRequest(); xhr.open('GET', sites[site].checkPageURL, true); xhr.setRequestHeader('Accept-Language','en-US,en;q=0.8,ru;q=0.6,uk;q=0.4,qya;q=0.001'); xhr.responseType = 'document'; xhr.timeout = 10000; xhr.withCredentials = true; xhr.onload = function() { processDoc(this.response, watcher); }; xhr.ontimeout = xhr.onerror = function(evt) { watcher.parentNode.appendChild(document.createElement('pre')).textContent = evt.type.charAt(0).toUpperCase() + evt.type.slice(1) + '.'; watcher.style.backgroundImage = 'none'; }; xhr.send(null); } /******************************************************************************/ function processDoc(doc, watcher) { var site = watcher.textContent; var siteData = netData[site]; var keyElements = doc.querySelectorAll(sites[site].keyElementsSelector); var info, news; if (keyElements.length) { var now = new Date(Date.now()).toLocaleString(); var curEntries = [].map.call(keyElements, function(el) { el.search = ''; return el.href; }); var curEntriesTitles = [].map.call(keyElements, function(el) { return el.textContent; }); if (siteData.lastEntries.length) { var added = curEntries.filter(function(el) { return siteData.lastEntries.indexOf(el) == -1; }).map(function(el) { var ci = curEntries.indexOf(el); return '+ ' + (ci + 1) + '\t<a href="' + el + '">' + curEntriesTitles[ci] + '</a>'; }); var removed = siteData.lastEntries.filter(function(el) { return curEntries.indexOf(el) == -1; }).map(function(el) { var li = siteData.lastEntries.indexOf(el); return '- (' + (li + 1) + ')\t<a href="' + el + '">' + siteData.lastEntriesTitles[li] + '</a>'; }); var risen = siteData.lastEntries.filter(function(el, li) { var ci = curEntries.indexOf(el); return ci > -1 && ci < li; }).map(function(el) { var ci = curEntries.indexOf(el); return '↑ ' + (siteData.lastEntries.indexOf(el) + 1) + '\t→\t' + (ci + 1) + '\t<a href="' + el + '">' + curEntriesTitles[ci] + '</a>'; }); var fallen = siteData.lastEntries.filter(function(el, li) { return curEntries.indexOf(el) > li; }).map(function(el) { var ci = curEntries.indexOf(el); return '↓ ' + (siteData.lastEntries.indexOf(el) + 1) + '\t→\t' + (ci + 1) + '\t<a href="' + el + '">' + curEntriesTitles[ci] + '</a>'; }); news = added.length || removed.length || risen.length || fallen.length; info = now + ' (previous check: ' + siteData.lastCheck + ')<hr>' + (news? [added.join('\n'), removed.join('\n'), risen.join('\n'), fallen.join('\n')] .filter(function(el){return el.length;}).join('\n\n') : 'No news.' ); } else { info = now + '<hr>First launch. Data saved (' + curEntries.length + ' entries).'; } watcher.parentNode.appendChild(document.createElement('pre')).innerHTML = info; var historyHeader = watcher.parentNode.appendChild(document.createElement('pre')); var historyOptionLabel = historyHeader.appendChild(document.createElement('label')); var historyOption = historyOptionLabel.appendChild(document.createElement('input')); historyOption.type = 'checkbox'; historyOption.checked = siteData.saveHistory; historyOption.addEventListener('click', toggleHistory); historyOptionLabel.appendChild(document.createTextNode('Save history')); var clearer = historyHeader.appendChild(document.createElement('button')); clearer.type = 'button'; clearer.textContent = 'Clear history'; clearer.disabled = !siteData.history.length; clearer.addEventListener('click', clearHistory); watcher.parentNode.appendChild(document.createElement('pre')).innerHTML = siteData.history.length? siteData.history.join('\n<hr>\n') : 'No history.'; siteData.lastEntries = curEntries; siteData.lastEntriesTitles = curEntriesTitles; if (news && siteData.saveHistory) {siteData.history.unshift(info);} siteData.lastCheck = now; localStorage['IMDbChartsHistory.netData'] = JSON.stringify(netData); } else { watcher.parentNode.appendChild(document.createElement('pre')).textContent = 'Parsing error.'; } watcher.style.backgroundImage = 'none'; } /******************************************************************************/ function toggleHistory(evt) { var site = evt.target.parentNode.parentNode.parentNode.querySelector('a').textContent; var siteData = netData[site]; siteData.saveHistory = evt.target.checked; localStorage['IMDbChartsHistory.netData'] = JSON.stringify(netData); } /******************************************************************************/ function clearHistory(evt) { var site = evt.target.parentNode.parentNode.querySelector('a').textContent; var siteData = netData[site]; siteData.history = []; evt.target.parentNode.parentNode.querySelector('pre:last-of-type').innerHTML = 'History cleared.'; localStorage['IMDbChartsHistory.netData'] = JSON.stringify(netData); evt.target.disabled = true; } /******************************************************************************/ </script> </head> <body></body> </html>
      
      







VII. アプリ





1. IE — , HTML-. , IE , :



-
 <!doctype html> <html> <head><meta charset="UTF-8"><title>Bookmarklets</title></head> <body style="text-align: center; font-family: monospace; font-size: 12pt;"> <p><a href="javascript:(function(url, xhr) {if(!url) {return;}xhr = new XMLHttpRequest();try {xhr.open('HEAD', url, true);}catch (e) {alert(e.name + ': ' + e.message);return;}xhr.setRequestHeader('Accept-Language', 'en-US,en;q=0.8,ru;q=0.6,uk;q=0.4,qya;q=0.001');xhr.responseType = 'document';xhr.timeout = 10000;xhr.withCredentials = true;xhr.onload = function(evt, l) {l = this.getResponseHeader('Content-Length');alert([this.responseURL || '?',this.getResponseHeader('Content-Type') || '?',this.getResponseHeader('Last-Modified') || '?',l ?[l + ' B',(l / 1024) .toFixed(3) + ' kB',(l / 1048576) .toFixed(3) + ' MB',(l / 1073741824).toFixed(3) + ' GB'].join(' \u2248 '):'?'].join('\n\n') + '\n\n');};xhr.ontimeout = xhr.onerror = function(evt) {alert(evt.type.charAt(0).toUpperCase() + evt.type.slice(1) + '.');};try {xhr.send(null);}catch (e) {alert(e.name + ': ' + e.message); return;}})(document.activeElement.href || prompt('URL:'))"> </a></p> <p><a href="javascript:(function(e,t,n,a,A,i,r,o,l,p,d,s){function h(e,t){s.style.backgroundImage='url('+n+')',t=new XMLHttpRequest;try{t.open('GET',e.href,!0)}catch(a){return s.style.backgroundImage='none',void(s.textContent=a.name+': '+a.message)}t.setRequestHeader('Accept-Language','en-US,en;q=0.8,ru;q=0.6,uk;q=0.4,qya;q=0.001'),t.responseType='document',t.timeout=1e4,t.withCredentials=!0,t.onload=function(){s.style.backgroundImage='none',this.response&&this.response.title?(s.textContent=this.response.title,e.setAttribute('data-breadcrumbs-doc-title',this.response.title)):(s.textContent='?',e.setAttribute('data-breadcrumbs-doc-title','?'))},t.ontimeout=t.onerror=function(e){s.style.backgroundImage='none',s.textContent=e.type.charAt(0).toUpperCase()+e.type.slice(1)+'.'};try{t.send(null)}catch(a){s.style.backgroundImage='none',s.textContent=a.name+': '+a.message}}for(t=e.activeElement.href?e.activeElement:location,n='data:image/gif;base64,R0lGODlhEAAQAOMIAAAAABoaGjMzM0xMTGZmZoCAgJmZmbKysv///////////////////////////////yH/C05FVFNDQVBFMi4wAwEAAAAh+QQBCgAIACwAAAAAEAAQAAAESBDJiQCgmFqbZwjVhhwH9n3hSJbeSa1sm5GUIHSTYSC2jeu63q0D3PlwCB1lMMgUChgmk/J8LqUIAgFRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+UKgmFqbpxDV9gAA9n3hSJbeSa1sm5HUMHTTcTy2jeu63q0D3PlwDx2FQMgYDBgmk/J8LqWPQuFRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+YSgmFqb5xjV9gQB9n3hSJbeSa1sm5EUQXQTADy2jeu63q0D3PlwDx2lUMgcDhgmk/J8LqUPg+FRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+cagmFqbJyHV9ggC9n3hSJbeSa1sm5FUUXRTEDy2jeu63q0D3PlwDx3FYMgAABgmk/J8LqWPw+FRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+QihmFqbZynV9gwD9n3hSJbeSa1sm5GUYXSTIDy2jeu63q0D3PlwDx3lcMgEAhgmk/J8LqUPAOBRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+UqhmFqbpzHV9hAE9n3hSJbeSa1sm5HUcXTTMDy2jeu63q0D3PlwDx0FAMgIBBgmk/J8LqWPQOBRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+YyhmFqb5znV9hQF9n3hSJbeSa1sm5EUAHQTQTy2jeu63q0D3PlwDx0lEMgMBhgmk/J8LqUPgeBRhV6z2q0VF94iJ9pOBAAh+QQBCgAPACwAAAAAEAAQAAAESPDJ+c6hmFqbJwDV9hgG9n3hSJbeSa1sm5FUEHRTUTy2jeu63q0D3PlwDx1FIMgQCBgmk/J8LqWPweBRhV6z2q0VF94iJ9pOBAA7',a=e.createElement('div'),a.setAttribute('data-breadcrumbs-main',''),a.appendChild(e.createElement('style')).textContent='div[data-breadcrumbs-main] {position:fixed; top:0px; left:0; z-index:999999; width:100%; padding:10px !important; background-color:white !important; outline:1px solid black !important; font-size: 12pt !important; text-align: left !important;}\ndiv[data-breadcrumbs-main] a {font-size: 12pt !important; text-decoration: underline !important;}\ndiv[data-breadcrumbs-main] div {margin-top: 20px!important; color: silver !important;}\ndiv[data-breadcrumbs-info-title] {background-repeat: no-repeat !important; background-position: left center !important; padding-left: 20px !important;}',A=t.protocol+(/:[\/][\/]/.test(t.href)?'//':''),a.appendChild(e.createElement('span')).textContent=A,i=t.hostname.split('.'),r=i.length,r>1&&(i.splice(r-2,2,i.slice(r-2).join('.')),r--),o=0;r>o;o++)l=i[o],o>0&&(a.appendChild(e.createElement('span')).textContent='.'),p=a.appendChild(e.createElement('a')),p.textContent=l,p.href=A+i.slice(o).join('.');if(A+=t.hostname,t.port&&/:\d+$/.test(t.host)&&(a.appendChild(e.createElement('span')).textContent=':',p=a.appendChild(e.createElement('a')),p.textContent=t.port,A+=':'+t.port,p.href=A),a.appendChild(e.createElement('span')).textContent='/',A+='/',t.pathname.length>1)for(i=t.pathname.split('/'),i.shift(),r=i.length,o=0;r>o;o++)l=i[o],r-1>o?(p=a.appendChild(e.createElement('a')),p.textContent=l,A+=l,a.appendChild(e.createElement('span')).textContent='/',A+='/',p.href=A):''!==l&&(p=a.appendChild(e.createElement('a')),p.textContent=l,A+=l,p.href=A);if(t.search)for(i=t.search.split('&'),r=i.length,i[0]=i[0].substring(1),a.appendChild(e.createElement('span')).textContent='?',A+='?',o=0;r>o;o++)l=i[o],o>0&&(a.appendChild(e.createElement('span')).textContent='&',A+='&'),p=a.appendChild(e.createElement('a')),p.textContent=l,A+=l,p.href=A;t.hash&&(a.appendChild(e.createElement('span')).textContent='#',p=a.appendChild(e.createElement('a')),p.textContent=t.hash.substring(1),A+=t.hash,p.href=A),a.querySelector('a:last-of-type').href==location.href&&a.querySelector('a:last-of-type').setAttribute('data-breadcrumbs-doc-title',e.title),d=a.appendChild(e.createElement('div')),d.setAttribute('data-breadcrumbs-info-url',''),d.textContent='URL',s=a.appendChild(e.createElement('div')),s.setAttribute('data-breadcrumbs-info-title',''),s.textContent='Title',a.addEventListener('mouseover',function(e,t,n){(t=e.target.href)&&(d.textContent=t,(n=e.target.getAttribute('data-breadcrumbs-doc-title'))?s.textContent=n:h(e.target))}),a.addEventListener('dblclick',function(){a.parentNode.removeChild(a)}),e.body.appendChild(a)})(document)"> </a></p> </body> </html>
      
      







2. - , , , ( IE):



Internet Explorer 11のブックマヌクレットストレヌゞ圢匏、制限ず暗黙のルヌル、朜んでいるバグ



ブックマヌクレットXPathが利甚できず、セレクタヌずDOMナビゲヌションメ゜ッドが十分でない堎合



ブックマヌクレット甚の信頌できるlocalStorage



ご枅聎ありがずうございたした








PS 仮想マシンをチェックするず、2015幎7月22日ファむルバヌゞョンによるのMS Edgeバヌゞョン11.00.10240.16397で、20.10240.16384.0蚭定の情報によるでもあるこずが瀺されたす



。基本およびサヌドパヌティのCookieはデフォルトで有効になっおいるため、远加の蚭定XMLHttpRequest.withCredentials



は䞍芁です。



b。 null Access-Control-Allow-Origin



リダむレクト䞭の゚ラヌは発生しなくなりたした。リダむレクト埌、すべおが意図したずおりに機胜するためOrigin



送信されnull



たす。



c。プロパティnavigator.languages



はただ実装されおいたせん。



d。プロパティXMLHttpRequest.responseURL



はただ実装されおいたせん。



e。localStorage



ロヌカルペヌゞのロヌカルペヌゞのストレヌゞはただ実装されおいたせん。



All Articles