提供一份 HTML 文件,並設定 Content-Type: text/html; charset=utf-8,在文件 head 中加入標題與描述,並在 body 中放入可閱讀的內容。本 Mac 操作指南會建立一個合成頁面,並確認單一回應包含這三者。

此任務是準備一份可由瀏覽器讀取的公開文件,先使用本機預覽,再將相同結構移轉到發布系統。範例只包含關於紙張形狀的虛構文字,不需要外部素材。

單一類型的 HTTP 回應中應包含什麼?

「類型」指的是回應宣告了媒體類型。Content-Type 欄位會告知接收方表示內容的格式及預期處理方式。此處的格式是 HTML。它不會提供逐欄位的應用程式結構描述。RFC 9110,第 8.3 節

HTTP/1.1 回應包含狀態行、標頭欄位、一個空白行,以及可選的本文。因此,你可以在標頭中傳送傳輸中繼資料,並在本文中放入完整文件,無須另外發出中繼資料請求。RFC 9112,第 2.1 節

這項發布任務可依照以下配置指南。它區分描述 HTTP 表示內容的資訊與描述頁面的資訊。

資訊 位置 範例
表示內容的格式與編碼 HTTP 標頭 Content-Type: text/html; charset=utf-8
文件標題 HTML head <title>Paper Shapes: Circle and Square</title>
頁面摘要 HTML head <meta name="description" content="A short guide to arranging paper circles and squares.">
面向讀者的內容 HTML body 標題、引言與排列說明

WHATWG 將 title 元素定義為文件的標題或名稱,並將 description 中繼資料值定義為頁面的描述。使用一個 title,並且最多只使用一個 description 宣告。由於它們位於 HTML 文件內,內容與描述性中繼資料會一起傳送。HTML 標準:文件中繼資料

如何在 Mac 上建立可運作的預覽?

開啟 Terminal,並確認可用的命令:

python3 --version
curl --version

以下程式需要 Python 3.7 或更新版本,且只使用其標準函式庫。如果無法使用 python3,請依照官方 macOS 安裝說明操作,然後重新開啟 Terminal。Python 文件說明了安裝程式,以及如何從終端機執行 python3。在 macOS 上使用 Python

將以下完整區塊貼到 Terminal,包括開頭的命令和最後一行 PY。這會直接執行程式,不會建立或覆寫檔案。檢查頁面時,請讓這個終端機視窗保持執行。

python3 - <<'PY'
from html import escape
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer

TITLE = "Paper Shapes: Circle and Square"
SUMMARY = "A short guide to arranging paper circles and squares."
PAGE = f"""<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{escape(TITLE)}</title>
<meta name="description" content="{escape(SUMMARY, quote=True)}">
</head>
<body>
<main>
<h1>{escape(TITLE)}</h1>
<p>{escape(SUMMARY)}</p>
<h2>Try a simple arrangement</h2>
<p>Place one paper circle beside one paper square.</p>
<p>Switch their positions — then compare the two arrangements.</p>
</main>
</body>
</html>
""".encode("utf-8")

class Handler(BaseHTTPRequestHandler):
    protocol_version = "HTTP/1.1"

    def respond(self, include_body):
        if self.path != "/paper-shapes":
            self.send_error(404, "Page not found")
            return
        self.send_response(200)
        self.send_header("Content-Type", "text/html; charset=utf-8")
        self.send_header("Content-Length", str(len(PAGE)))
        self.end_headers()
        if include_body:
            self.wfile.write(PAGE)

    def do_GET(self):
        self.respond(True)

    def do_HEAD(self):
        self.respond(False)

if __name__ == "__main__":
    with ThreadingHTTPServer(("127.0.0.1", 8000), Handler) as server:
        print("Preview: http://127.0.0.1:8000/paper-shapes", flush=True)
        try:
            server.serve_forever()
        except KeyboardInterrupt:
            pass
PY

此處理常式使用 Python 文件所述的回應方法:send_response() 會開始回應,send_header() 會加入欄位,而 end_headers() 會在寫入本文位元組前結束標頭區段。Python HTTP 伺服器文件

此範例刻意只定義一次 TITLE 和 SUMMARY。這些值同時提供中繼資料與可見文字,讓這份小型文件更容易一致地修改。對於較長的頁面,描述可以與開場段落不同,但仍須準確概述相同主題。

頁面會先編碼,再計算長度。HTTP 將 Content-Length 定義為八位元組,也就是位元組;若計算字元數,這個範例中的破折號就會導致結果錯誤。RFC 9110,第 8.6 節

如何確認內容與中繼資料一併送達?

開啟第二個 Terminal 視窗並執行此命令。它會發出一般文件請求,並顯示回應標頭與內容:

curl -i --max-time 10 http://127.0.0.1:8000/paper-shapes

-i 選項會讓回應標頭與本文一同顯示在輸出串流中。時間限制會將傳輸時間限制在十秒內。這些選項記載於 curl 命令列手冊。

依序檢查輸出:

  1. 狀態行應顯示 200 OK。
  2. 單一 Content-Type 欄位應宣告 text/html; charset=utf-8。
  3. 標頭區段的空白行之後,HTML 應包含標題與描述。
  4. 同一份本文應包含紙張形狀的說明。
  5. 破折號應在解碼後的文字中正確顯示。

接著,在 Safari 的網址列輸入 http://127.0.0.1:8000/paper-shapes。可見頁面應顯示標題、摘要與說明。描述宣告屬於中繼資料;應在傳回的標記中檢查它是否存在,而不是從頁面外觀推斷。

你也可以檢查僅傳回標頭的路徑:

curl -I --max-time 10 http://127.0.0.1:8000/paper-shapes

這會傳送 HEAD,因此無法確認本文是否包含標題或描述。HEAD 回應會省略內容,但會描述對應的表示內容;請使用前面的 GET 檢查來查看實際文件。RFC 9110,第 8.2 節

如果預覽無法正常運作,請根據症狀採取下一步:

症狀 下一步
啟動時顯示位址已在使用中 在程式中將 8000 改為 8001,重新執行程式,並在每個預覽命令中使用 8001。
請求顯示連線失敗 確認第一個終端機仍顯示預覽正在執行,且連接埠相符。
回應為 404 請使用 /paper-shapes,不要多加其他內容;此範例不接受結尾斜線或查詢字串。
瀏覽器仍顯示舊版本 按下 Control-C 停止程式,重新執行已編輯的區塊,然後重新載入頁面。
標題正確,但缺少中繼資料 檢查 GET 輸出,並確認宣告位於文件 head 內。

Google 搜尋可以從這個回應中使用哪些內容?

描述明確的標題、準確的描述,以及實用的可見文字,都是 Google 用來呈現頁面的已知輸入來源。Google 列出的自動產生標題連結輸入來源包括 title 元素、主要可見標題、標題元素和其他來源。請確保這些資訊都與文件主題一致。調整搜尋結果中的標題連結

Google 主要根據頁面內容產生摘要,有時會在 meta description 更準確描述頁面時採用它。不同搜尋可能會產生不同摘要。請將描述視為實用摘要,而非固定的搜尋結果說明文字。控制搜尋結果中的摘要

在這個合成範例中,描述承諾提供簡短的排列指南,而本文也確實提供該指南。替換範例文字時,請明確確認兩者關係:只閱讀描述的人,應能對頁面內容形成準確的預期。

加入自訂的中繼資料名稱,並不代表 Google 支援這些名稱。Google 表示,它會忽略不支援的 meta 標籤。搜尋用途的中繼資料應使用 Google 文件記載的欄位;若是為自己的應用程式發明的欄位,則需要另外定義使用它的程式。Google 支援的中繼標籤與屬性

如何將預覽轉化為公開發布模式?

本操作指南中的本機網址是桌面預覽,不是已發布的頁面。Python 也說明,http.server 不建議用於正式環境。請將 HTML 結構與回應需求移轉到你的發布系統,不要將此示範當作公開託管服務。Python HTTP 伺服器文件

如果你使用內容管理系統,請查看其中記載的頁面標題與 meta description 設定。Google 指出,CMS 可能提供搜尋設定,而不是直接編輯 HTML。請將這些設定對應到此處示範的欄位,再檢查產生的文件回應。Google 關於新增 meta description 的指南

HTTP 確實支援多部分表示內容,但那是另一種封裝方式。對於這項可由瀏覽器讀取的文件任務,現有的 HTML 結構已能在同一份表示內容中容納內容與文件中繼資料。選用多部分格式會帶來消費端處理需求,而本操作指南並不需要這項需求。RFC 9110,第 8.3.3 節

完成條件很明確:一次成功的文件請求會傳回正確的媒體類型、完整的 HTML 本文、準確的標題與描述,以及讀者前來閱讀的文字。請將這項檢查同時套用於最終公開回應與本機預覽,確保發布系統的輸出符合你準備好的文件。

來源