Skip to content

Browser 面板

Browser 面板在題目頁面裡呈現題目的應用程式。它有自己的網址列、自己的導覽按鈕、自己的一份歷史紀錄,這三者都不與你正在讀這一頁的真實瀏覽器分頁共用。

面板剛開啟時

網址列預先填入該題專屬的網址 https://challenge-<slug>.localhost/,其中 <slug> 是該題的識別代號。

在載入任何頁面之前,內容區中央顯示 Enter a URL and press Go

題目 runtime 還沒就緒時,Go 按鈕停用,文字換成 ;就緒之後才變回 Go。而 runtime 由未就緒轉為就緒的那一刻,面板會自己對網址列上的網址發出第一次導覽——第一頁不需要你按 Go

網址列左側永遠有一個 🔒 圖示。它是固定裝飾,不隨網址改變,也不代表任何連線狀態。

網址列

網址列是一個可自由編輯的文字輸入框。輸入任何網址後按 Enter 即可導覽;EnterGo 按鈕送出的是同一個導覽事件,兩者可互相替代。欄位空白時顯示提示文字 https://challenge-…

動手改它之前有兩個行為要先知道:

  • 導覽進行中你打的字不會被蓋掉。 導覽還沒回來時改寫網址列,回應到達也不會覆蓋你輸入的內容。反之,你沒有改過它的話,導覽完成後欄位會被改寫成實際抵達的網址。
  • runtime 未就緒時按 Enter 完全沒有反應。 輸入框不會停用,也不會跳出任何訊息,導覽在送出請求之前就被擋掉。螢幕上唯一的線索是 Go 按鈕顯示

導覽按鈕

網址列左邊有三顆按鈕。它們只在桌機寬度出現——手機或窄視窗會把整組隱藏,只留下網址列與 Go

控制項做什麼何時停用tooltip
← 上一頁重新顯示面板歷史紀錄中的前一筆目前位置之前沒有紀錄時,包含第一頁剛載入完成的當下可用時 Back,停用時 No earlier page in this tab
→ 下一頁重新顯示面板歷史紀錄中的後一筆目前位置之後沒有紀錄時可用時 Forward,停用時 No later page in this tab
↻ 重新載入重新抓取目前這筆歷史紀錄的網址題目 runtime 未就緒,或上一次重新載入還沒回來;回應到達後恢復固定是 Reload,停用時也不換字

上一頁與下一頁只看歷史紀錄,不看 runtime 是否就緒。所以 runtime 重建期間——也就是 Go 顯示 、重新載入停用的那段時間——只要已經有歷史,這兩顆鈕仍然可按。按下去也只是把存下來的舊畫面搬回螢幕上。

導覽歷史的範圍

這份歷史紀錄屬於這個題目頁面的 Browser 面板。它不與其他題目共用,也不是真實瀏覽器的歷史:你瀏覽器自己的上一頁不會回到面板的前一頁。

  • 上一頁與下一頁不會重新發出任何請求。 它們把先前存下來的畫面搬回顯示,因此 Network Traffic 記錄不會多一筆。
  • 回上一頁之後再導覽到新網址,會丟掉「下一頁」方向的紀錄。 一旦往回走再往新的地方去,原本前方的紀錄全部作廢。
  • 導覽到目前這筆紀錄的同一個網址時,是原地取代而不是新增一筆。 點一個指回本頁的連結、或對同一個網址再按一次 Go,歷史位置都不會前進——所以上一頁不會因此變成可按。真實瀏覽器在這裡的行為相反。
  • 重新載入停在同一個網址時會留在原位。 網址沒變就原地更新該筆紀錄,「下一頁」方向的紀錄保留;若被導向到別的網址,就算一次新導覽並新增一筆。
  • 上一頁與下一頁會作廢正在進行中的導覽。 已經送出的請求照樣送出、照樣記進流量記錄,但它的回應不會顯示,回應帶的 Set-Cookie 也不會寫進面板的 cookie jar。

正在看的畫面若是用上一頁/下一頁叫回來的,內容上方會出現一條說明列 cached view · captured <時間> · press ↻ to refetch。如果從那個畫面被存下來到現在 session cookie 已經改變,同一條說明列會轉成警告色並補上 · session cookies have changed since this capture——螢幕上這一頁是在與現在不同的 cookie 之下被記錄下來的。

重新載入

重新載入一律以 GET 重送。它不會重送 POST 的本體,所以面板不會像真實瀏覽器那樣詢問你要不要重新送出表單。

它抓的是目前這筆歷史紀錄裡存的網址,不是網址列上的文字——你打到一半、還沒送出的網址會在按下它的時候被還原掉。

頁面內的連結與表單

頁面內的點擊與表單送出都會被面板攔下,改由面板自己重新發出請求。

在頁面裡做的事面板送出什麼
點一個連結一個全新的 GET,並帶上目前網址當作 Referer 標頭,可在流量記錄裡看到
點一個 href 為空或以 # 開頭的連結什麼都不送:沒有請求、沒有流量記錄、沒有歷史紀錄
送出 GET 表單把欄位接成查詢字串附在目標網址後面,因此網址列會出現 ?key=value
送出 POST 表單依表單的 enctype 組出 multipart/form-data 或 urlencoded 的本體發出請求;成功的回應和一般導覽一樣進入歷史紀錄
送出一個沒有 action 屬性的表單目標取自網址列當下的文字,不是目前這一頁的網址。先改網址列再送出,表單就會送到被改過的那個網址

runtime 未就緒期間什麼都不會送出。即使螢幕上是用上一頁叫回來的舊畫面也一樣——點它的連結、送出它的表單,都不會產生請求。

面板自己維護一份 cookie jar,jar 裡有的 Cookie 會在後續請求自動帶回,並出現在 Network Traffic 面板顯示的請求標頭裡。但在 Python 與 PHP 題目上,進到這份 jar 的並不是題目原本送出的 Set-Cookie:面板解不開平台用來搬運這些標頭的格式,存進去的是一段無意義的字串。那段字串照樣會被送出、照樣出現在流量記錄裡,但題目那一端認不得它,所以在這裡登入之後狀態不會延續,而且全程沒有任何錯誤訊息。見疑難排解

另外兩個行為會讓「你看到的」與「實際送出的」不一致:

  • 連續的轉址會自動跟隨,最多五次。 整條轉址鏈只在最終網址留下一筆歷史紀錄。跟滿五次之後不會出現任何錯誤:第六個 3xx 回應會被當成一般回應直接顯示(通常是空白頁)並寫進歷史紀錄,網址列停在發出該次轉址的來源網址。
  • 快速重複導覽不會取消任何東西。 連按 Go 或快速連點多個連結,每一筆請求都照樣送出、照樣記進流量記錄,畫面只顯示最後一次導覽的結果。先前的回應是被丟棄,不是被中止。

回應怎麼呈現

HTML 回應顯示在一個 sandbox 的 iframe 裡。該 sandbox 給了 script 與表單,但沒有給同源存取,所以題目應用程式的 JavaScript 讀不到實驗室本身的 DOM、cookie 與 localStorage。面板有自己的 cookie jar,與你瀏覽器的 cookie 儲存區分開——要看它送出什麼請走流量記錄,不要用瀏覽器的開發者工具。

回應若不是 text/html 就完全不進 iframe,改以純文字區塊呈現。application/json 會先排版成縮排後的 JSON 再顯示。

導覽失敗時

導覽失敗時內容上方會多出一條說明列:Navigation failed — the challenge runtime did not respond。任何導覽失敗都會顯示它,不只是重新載入——點連結失敗一樣看得到。

除此之外什麼都不變。原本在螢幕上的那一頁維持原狀,網址列的文字也保持原狀,所以失敗看起來很像「按了沒反應」。那條錯誤列就是要找的東西。

runtime 若一直沒有回來,疑難排解有已知限制的完整清單與各自的處理方式。