こんにちは!!こんにちは!! moriyamaです。
早速ですが、特定WEBサイトのアクセス時に自作scriptを走らせたい時ってありませんか?
私はあります。読者の皆さんもありますよね?
いつかは実現したいと常日頃から考えており、今回ついに実装できたので記しておきます。
拡張機能では駄目なのか?
bodyタグ内で走って問題ないなら、ぶっちゃけ駄目じゃないと思います。
ChromeやFireFoxなどのブラウザは拡張機能でjavascriptを組み込めたり出来ますが、
headタグに組み込めるものは見たことがありません。
例えば純粋なjavascriptで書かれたWEBページでDOM操作したい際に、
面倒臭がってjQueryでscriptを書いても、jQuery本体を先に読み込ませる必要がありますよね?
bodyタグで読み込んでも、実行順序で不都合が起きたこともあったため、
headタグにscriptを埋め込めないかと常々考えていました。
どう実現したのか?
ローカルにnginxでプロキシサーバを立てました!
完!!!で締めたいところですが、もう少し詳しく説明します。
nginx の proxy_passを使ってリクエストを流し、Luaのスクリプトを走らせてレスポンスを改変します。
そのためluaモジュールが組み込まれたnginx(OpenResty)を使いました。
フォルダ構成は、シンプルにこんな感じです↓
. ├── docker-compose.yml └── nginx ├── default.conf └── src ├── body_filter.lua └── script.js
ファイルの中身
■ docker-compose.yml
version: '3' services: nginx: image: openresty/openresty:centos ports: - 8880:80 volumes: - ./nginx/default.conf:/etc/nginx/conf.d/default.conf - ./nginx/src:/etc/nginx/src
■ nginx/default.conf
server { listen 80; location / { # プロキシ設定 proxy_pass 'https://iko-yo.net/'; proxy_set_header Accept-Encoding ""; # luaコードのキャッシュ設定 #lua_code_cache off; # コンテンツ長が変動するため、ヘッダ書き換え header_filter_by_lua_block { ngx.header.content_length = nil } # コンテンツ内容の改変 body_filter_by_lua_file '/etc/nginx/src/body_filter.lua'; } }
■ nginx/src/body_filter.lua
-- jsファイルを読み込み function load_script() local file = io.open("/etc/nginx/src/script.js", "r") local script = file:read("*a") file:close() return script end -- 置換する文字列生成 local replace = "<head><script>" .. load_script() .. "</script>" -- body書き換え ngx.arg[1] = ngx.re.sub(ngx.arg[1], "<head>", replace)
■ nginx/src/script.js
if (confirm('動いた?')) { console.log('動いたらしい'); }
苦労した箇所
実装時はLua上でレスポンス内容を出力しながら試していましたが、
文字化けが酷く、内容が全く読めませんでした。
そのため置換処理も走らず、吐き出されるHTMLは変化せず四苦八苦。
string.upper等の文字列処理を試しても、ブラウザ上ではHTML認識されず、更には文字化けテキストが表示され悩まされ。
UTF8のライブラリを使い、エンコードしてみても駄目だったのです。
色々調べているうちに、偶然、解決方法を見つけました。
HTTPヘッダのAccept-Encoding が原因でした。
レスポンス本文が圧縮されている場合、
中身を出力したところで、エンコード関係なく文字化けしている様に見えるわけですね!
実際に動かしてみる
こうなりました!
各ページで、javascriptのconfirmが動作している様子が伺えますね!
最後に
思った通りに実装するのはなかなか難しいですが、動いた時は感無量ですね!