Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 10726] ファイルの概要

このコミットは、Go言語の公式ドキュメントツール兼サーバーであるgodocに、OpenSearch Description Document (OSDD) を追加するものです。これにより、godocの検索機能をWebブラウザの検索バーやその他のOpenSearch対応アプリケーションに統合できるようになります。ユーザーはブラウザから直接godocのドキュメントを検索できるようになり、利便性が向上します。

コミット

  • コミットハッシュ: ecf4a9216edfdcc48327382697fed5d98d7faf46
  • Author: Christoph Hack christoph@tux21b.org
  • Date: Mon Dec 12 18:01:06 2011 -0500

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/ecf4a9216edfdcc48327382697fed5d98d7faf46

元コミット内容

godoc: added an opensearch description document.

R=golang-dev, r, tux21b, rsc
CC=golang-dev
https://golang.org/cl/5479062

変更の背景

godocはGo言語のパッケージドキュメントを生成し、Webサーバーとして提供するツールです。以前から検索機能は備わっていましたが、その検索機能はgodocのWebインターフェース内でのみ利用可能でした。

この変更の背景には、ユーザーがより手軽にgodocのドキュメントを検索できるようにしたいというニーズがありました。OpenSearchは、Webサイトの検索機能を標準的なXML形式で記述し、Webブラウザや他のアプリケーションがその検索機能を利用できるようにする技術です。OpenSearch Description Documentを提供することで、ユーザーはgodocのWebサイトを訪問することなく、ブラウザの検索バーから直接Goのドキュメントを検索できるようになります。これにより、開発者のワークフローが効率化され、Goドキュメントへのアクセス性が向上します。

前提知識の解説

godocとは

godocは、Go言語のソースコードからドキュメントを抽出し、HTML形式で表示するツールです。Goのコードは、コメントの書き方によって自動的にドキュメントとして認識される仕組みがあり、godocはそのコメントを解析して整形されたドキュメントを生成します。また、godocは単なるドキュメント生成ツールとしてだけでなく、ローカルでドキュメントサーバーを起動する機能も持っています。これにより、開発者は自分のマシン上でGoの標準ライブラリやサードパーティライブラリのドキュメントを簡単に参照できます。

OpenSearchとは

OpenSearchは、Webサイトの検索機能を記述するためのXMLベースの標準フォーマットです。これにより、Webサイトの検索機能をWebブラウザやデスクトップアプリケーション、その他の検索アグリゲーターなどのクライアントアプリケーションに統合することが可能になります。ユーザーは、OpenSearchに対応したブラウザの検索バーにキーワードを入力するだけで、特定のWebサイトの検索結果を直接取得できるようになります。

OpenSearch Description Document (OSDD) の役割

OpenSearch Description Document (OSDD) は、OpenSearchの核となる部分です。これはXML形式のファイルで、Webサイトの検索機能に関するメタデータ(サイト名、説明、検索クエリの送信方法、検索結果のURLテンプレートなど)を記述します。Webブラウザは、Webページ内に埋め込まれたOSDDへのリンクを検出すると、そのサイトの検索機能をブラウザの検索エンジンリストに追加するオプションをユーザーに提供できます。

OSDDには以下のような主要な要素が含まれます。

  • <ShortName>: 検索エンジンの短い名前(ブラウザの検索エンジンリストに表示される名前)。
  • <Description>: 検索エンジンの詳細な説明。
  • <Url>: 検索クエリを送信するためのURLテンプレート。{searchTerms}のようなプレースホルダーを使用して、ユーザーが入力した検索キーワードがどこに挿入されるかを示します。
  • <Image>: 検索エンジンに関連付けられたアイコンのURL。
  • <InputEncoding> / <OutputEncoding>: 入力および出力の文字エンコーディング。

Webブラウザとの連携

多くのモダンなWebブラウザ(Firefox, Chrome, Edgeなど)はOpenSearchをサポートしています。WebページがOSDDへの<link>タグをHTMLの<head>セクションに含んでいる場合、ブラウザはそのOSDDを自動的に検出し、ユーザーにそのサイトの検索機能をブラウザの検索エンジンに追加するオプションを提示します。一度追加されると、ユーザーはブラウザの検索バーから直接そのサイトのコンテンツを検索できるようになります。

技術的詳細

このコミットでは、godocのWebサーバー機能にOpenSearchのサポートを追加するために、以下の主要な変更が行われています。

  1. OpenSearch Description Document (opensearch.xml) の追加: lib/godoc/opensearch.xmlという新しいファイルが追加されました。このXMLファイルは、godocの検索機能に関するOpenSearchのメタデータを定義しています。

    • ShortNameは「godoc」
    • Descriptionは「The Go Programming Language」
    • Tagsは「go golang」
    • Urlテンプレートは{{.BaseURL}}/search?q={searchTerms}となっており、godocの検索エンドポイント/searchにクエリパラメータqとして検索キーワードが渡されることを示しています。{{.BaseURL}}は、godocサーバーのベースURLが動的に挿入されることを意味します。
    • Image/favicon.icoが指定されており、godocのファビコンが検索エンジンのアイコンとして使用されます。
  2. HTMLへのOpenSearchリンクの追加: lib/godoc/godoc.htmlに、OpenSearch Description Documentへの<link>タグが追加されました。

    {{if .SearchBox}}
    <link rel="search" type="application/opensearchdescription+xml" title="godoc" href="/opensearch.xml" />
    {{end}}
    

    この<link>タグは、godocのテンプレートエンジンによってSearchBox変数がtrueの場合にのみレンダリングされます。これにより、検索ボックスが表示されるページでのみOpenSearchの機能が提供され、不要な場合にリンクが追加されるのを防ぎます。type="application/opensearchdescription+xml"は、このリンクがOpenSearch Description Documentであることをブラウザに伝えます。href="/opensearch.xml"は、OSDDが/opensearch.xmlというパスで提供されることを示します。

  3. godocサーバーでのOpenSearch Description Documentの提供: src/cmd/godoc/godoc.goに、OpenSearch Description DocumentをHTTP経由で提供するための新しいハンドラとテンプレート処理ロジックが追加されました。

    • registerPublicHandlers関数内で、/opensearch.xmlパスに対する新しいHTTPハンドラserveSearchDescが登録されました。
      mux.HandleFunc("/opensearch.xml", serveSearchDesc)
      
    • テンプレート変数を管理するvarブロックに、searchDescXML *template.Templateが追加されました。これはopensearch.xmlの内容をパースしたテンプレートを保持します。
    • readTemplates関数内で、lib/godoc/opensearch.xmlファイルが読み込まれ、searchDescXMLテンプレート変数に格納されます。
      searchDescXML = readTemplate("opensearch.xml")
      
    • serveSearchDesc関数が新しく実装されました。この関数は、/opensearch.xmlへのリクエストを処理します。
      func serveSearchDesc(w http.ResponseWriter, r *http.Request) {
          w.Header().Set("Content-Type", "application/opensearchdescription+xml")
          data := map[string]interface{}{
              "BaseURL": fmt.Sprintf("http://%s", r.Host),
          }
          if err := searchDescXML.Execute(w, &data); err != nil {
              log.Printf("searchDescXML.Execute: %s", err)
          }
      }
      
      この関数は、まずレスポンスのContent-Typeヘッダをapplication/opensearchdescription+xmlに設定し、ブラウザがこれをOpenSearch Description Documentとして認識するようにします。次に、テンプレートに渡すデータとしてBaseURLを動的に生成します。r.Hostからリクエストのホスト名を取得し、http://を付加することで、godocが実行されている実際のURLをBaseURLとしてOSDDテンプレートに渡します。これにより、OSDD内のUrlテンプレートが正しく解決され、godocサーバーのベースURLが反映された検索URLが生成されます。最後に、searchDescXMLテンプレートを実行し、生成されたXMLをレスポンスとして書き込みます。エラーが発生した場合はログに出力します。

これらの変更により、godocはOpenSearchに対応した検索機能を提供できるようになり、Webブラウザとの連携が強化されました。

コアとなるコードの変更箇所

lib/godoc/godoc.html

--- a/lib/godoc/godoc.html
+++ b/lib/godoc/godoc.html
@@ -12,6 +12,9 @@
 <link rel="stylesheet" href="/doc/ie.css" type="text/css">
 <![endif]-->
 <script type="text/javascript" src="/doc/godocs.js"></script>
+{{if .SearchBox}}
+<link rel="search" type="application/opensearchdescription+xml" title="godoc" href="/opensearch.xml" />
+{{end}}
 </head>
 <body>
 <div id="container">

lib/godoc/opensearch.xml (新規ファイル)

<?xml version="1.0" encoding="UTF-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
  <ShortName>godoc</ShortName>
  <Description>The Go Programming Language</Description>
  <Tags>go golang</Tags>
  <Contact />
  <Url type="text/html" template="{{.BaseURL}}/search?q={searchTerms}" />
  <Image height="15" width="16" type="image/x-icon">/favicon.ico</Image>
  <OutputEncoding>UTF-8</OutputEncoding>
  <InputEncoding>UTF-8</InputEncoding>
</OpenSearchDescription>

src/cmd/godoc/godoc.go

--- a/src/cmd/godoc/godoc.go
+++ b/src/cmd/godoc/godoc.go
@@ -105,6 +105,7 @@ func registerPublicHandlers(mux *http.ServeMux) {
 	mux.HandleFunc("/doc/codewalk/", codewalk)
 	mux.HandleFunc("/search", search)
 	mux.Handle("/robots.txt", fileServer)
+	mux.HandleFunc("/opensearch.xml", serveSearchDesc)
 	mux.HandleFunc("/", serveFile)
 }
 
@@ -600,7 +601,8 @@ var (
 	packageHTML,
 	packageText,
 	searchHTML,
-	searchText *template.Template
+	searchText,
+	searchDescXML *template.Template
 )
 
 func readTemplates() {
@@ -615,6 +617,7 @@ func readTemplates() {
 	packageText = readTemplate("package.txt")
 	searchHTML = readTemplate("search.html")
 	searchText = readTemplate("search.txt")
+	searchDescXML = readTemplate("opensearch.xml")
 }
 
 // ----------------------------------------------------------------------------
@@ -809,6 +812,16 @@ func serveFile(w http.ResponseWriter, r *http.Request) {
 	fileServer.ServeHTTP(w, r)
 }
 
+func serveSearchDesc(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "application/opensearchdescription+xml")
+	data := map[string]interface{}{
+		"BaseURL": fmt.Sprintf("http://%s", r.Host),
+	}
+	if err := searchDescXML.Execute(w, &data); err != nil {
+		log.Printf("searchDescXML.Execute: %s", err)
+	}
+}
+
 // ----------------------------------------------------------------------------
 // Packages
 

コアとなるコードの解説

lib/godoc/godoc.html の変更

この変更は、godocのWebページがブラウザに読み込まれた際に、OpenSearch Description Documentの存在をブラウザに通知するためのものです。<link rel="search" ...>タグは、このページが検索機能を提供しており、その詳細がhref属性で指定されたXMLファイルにあることを示します。{{if .SearchBox}}というGoテンプレートの条件分岐は、godocのWebインターフェースで検索ボックスが表示される場合にのみ、このOpenSearchリンクをHTMLに含めるようにしています。これにより、不必要なリソースの読み込みや、検索機能がないページでの誤ったOpenSearchの検出を防ぎます。

lib/godoc/opensearch.xml の新規追加

このファイルは、godocの検索機能に関するOpenSearchの標準的なメタデータを定義しています。

  • <ShortName><Description>は、ブラウザの検索エンジンリストに表示されるgodocの識別情報を提供します。
  • <Tags>は、検索エンジンを分類するためのキーワードです。
  • <Url>要素は最も重要で、godocの検索エンドポイント(/search)と、ユーザーが入力する検索キーワード({searchTerms})がどのようにURLに組み込まれるかを定義しています。{{.BaseURL}}は、godocサーバーが実行されている実際のベースURLに置き換えられるプレースホルダーであり、これによりOSDDがどの環境でも正しく機能するようになります。
  • <Image>は、ブラウザの検索エンジンリストに表示されるアイコンを指定します。
  • <InputEncoding><OutputEncoding>は、検索クエリと結果の文字エンコーディングがUTF-8であることを示します。

src/cmd/godoc/godoc.go の変更

このファイルはgodocサーバーの主要なロジックを含んでいます。

  1. ハンドラの登録: mux.HandleFunc("/opensearch.xml", serveSearchDesc)は、/opensearch.xmlへのHTTPリクエストがserveSearchDesc関数によって処理されるようにルーティングを設定しています。これにより、ブラウザがOSDDを要求した際に、godocサーバーがそれを提供できるようになります。
  2. テンプレート変数の追加と読み込み: searchDescXML *template.Templateが宣言され、readTemplates関数内でopensearch.xmlファイルがGoのhtml/templateパッケージによってパースされ、この変数に格納されます。これにより、opocsearch.xmlが単なる静的ファイルとしてではなく、動的なデータ(BaseURLなど)を埋め込むことができるテンプレートとして扱われます。
  3. serveSearchDesc関数の実装: この関数は、/opensearch.xmlへのリクエストを処理する責任を負います。
    • w.Header().Set("Content-Type", "application/opensearchdescription+xml")は、レスポンスのMIMEタイプを正しく設定し、クライアント(ブラウザ)が受信したコンテンツをOpenSearch Description Documentとして解釈するように指示します。
    • data := map[string]interface{}{"BaseURL": fmt.Sprintf("http://%s", r.Host)}は、opensearch.xmlテンプレートに渡すデータを準備します。r.HostはHTTPリクエストのHostヘッダから取得され、godocサーバーが現在どのホスト名でアクセスされているかを正確に反映します。これにより、OSDD内のUrlテンプレートの{{.BaseURL}}が、godocサーバーの実際のURL(例: http://localhost:6060http://go.dev)に置き換えられます。
    • searchDescXML.Execute(w, &data)は、パース済みのopensearch.xmlテンプレートに動的に生成したBaseURLデータを適用し、その結果をHTTPレスポンスライターwに書き込みます。これにより、クライアントは完全に解決されたOpenSearch Description Documentを受け取ることができます。エラーが発生した場合は、log.Printfでログに出力されます。

これらの変更により、godocはOpenSearchの仕様に準拠した検索機能を提供し、Webブラウザとのシームレスな統合を実現しています。

関連リンク

参考にした情報源リンク