﻿# 講解 URL 網址結構與分享幾個相對路徑與絕對路徑的開發技巧

我覺得有很多人並不瞭解 [URL](http://en.wikipedia.org/wiki/Uniform_Resource_Locator) ( 或 [URI](http://en.wikipedia.org/wiki/Uniform_Resource_Identifier) ) 的全貌，一般人對 URL 的感覺就是「網址」而已，是一個十分不精確的描述，因為 URL 擁有一個很嚴謹的結構，也有很彈性的表示法，當你弄清楚觀念後，開發技巧之間的關係自然可以融會貫通。

我從 [RFC 3986: Uniform Resource Identifier (URI): Generic Syntax](http://tools.ietf.org/html/rfc3986) 的 [Syntax Components](http://tools.ietf.org/html/rfc3986#section-3) 章節擷取下圖：

![URL 基本結構](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/b6516afac29a33362edc-image_3.png) 

如上圖所示，在 URI 中有切分成許多部分，每個部分都有其意義，當你瞭解其意義之後，以後在記憶 URI 的時候就不用死背了。事實上在 [URI scheme - Wikipedia](http://en.wikipedia.org/wiki/URI_scheme) 頁面中的圖示更加完整，如下圖：

[![URL 基本結構 (點圖可放大)](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/c2d95b127660ad773077-image_thumb_1.png)](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/6d222c01b2395a51ede4-image_5.png) 

以下所列的網址([URL](http://en.wikipedia.org/wiki/Uniform_Resource_Locator)/[URI](http://en.wikipedia.org/wiki/Uniform_Resource_Identifier)/[URN](http://en.wikipedia.org/wiki/Uniform_Resource_Name))，全部都是 [URI](http://en.wikipedia.org/wiki/Uniform_Resource_Identifier) 的格式範例 (*注意：並非所有 URI 在瀏覽器中都可以使用*)

```
連結一般網站
http://blog.miniasp.com/post/2008/01/Useful-tool-grepWin.aspx#comment

連結需登入的 FTP 網站（直接在網址輸入帳號、密碼後，連結時瀏覽器就不會再出現登入視窗了）
ftp://username:password@ftp.example.com/upload/

使用 Windows Live Messenger 中附的 LiveCall 工具撥打電話到 +886-2-23222480
livecall:+886-2-23222480

使用 Skype 軟體撥打電話到 +886-2-23222480
callto:+886-2-23222480

取得 FTP 上的一個檔案
ftp://ftp.is.co.za/rfc/rfc1808.txt

以 HTTP 通訊協定取得網站上的一個檔案
http://www.ietf.org/rfc/rfc2396.txt

使用 LDAP 通訊協定取得一個物件
ldap://[2001:db8::7]/c=GB?objectClass?one

使用 mailto 協定發送訊息給 John.Doe@example.com
mailto:John.Doe@example.com

連結到 comp.infosystems.www.servers.unix 新聞群組
news:comp.infosystems.www.servers.unix

撥打電話到 +1-816-555-1212
tel:+1-816-555-1212

使用 telnet 連線到 192.0.2.16:80
telnet://192.0.2.16:80/

這是 URN 語法 (也是 URI 的一部份）
urn:oasis:names:specification:docbook:dtd:xml:4.1.2
```

以上講解的都是「絕對路徑」的「標準」表示法，在真實的世界裡，URI 可以說千變萬化，不照標準走的大有人在，而在 [URL normalization](http://en.wikipedia.org/wiki/URL_normalization) 這篇文章中有說明如何將 URL 進行「正規化」處理。所幸這類正規化的處理在 Browser 中幾乎都先幫我們處理過了，讓我們不至於真的要瞭解這麼多技術的細節才能讓 Web 正常運作。不過若自己在 Server 端處理 URI 格式的字串就不得不小心了，還好在 .NET 中有 [System.Uri 類別](http://msdn.microsoft.com/zh-tw/library/system.uri.aspx) 與 [UriBuilder 類別](http://msdn.microsoft.com/zh-tw/library/system.uribuilder.aspx) 幫我們處理掉了許多操作 Uri 的細節。

在實務開發上，許多人使用「相對路徑」來簡化 URI 的表示，最後我要講幾個在開發 Web 應用程式時常用的「相對路徑」開發技巧：

**技巧 1：忽略 scheme 與 authority 部分（見本文第 1 張圖示）**

這也是一般常見的「相對路徑」寫法，有時後會包含「路徑」的部分，有時後僅包括「檔名」：

```
# 同目錄下的 step2.aspx 頁面
step2.aspx

# 網站根目錄下的 index.aspx 頁面
/index.aspx

# 上層目錄的 sitemap.aspx 頁面
../sitemap.aspx

# 上兩層目錄的 default.htm 頁面
../../default.htm

# 上層目錄下的 images 目錄下的 dot 目錄下的 red.gif 檔案
../images/dot/red.gif
```

**技巧 2：忽略 scheme 與 authority 與 path 部分**

我個人常用此技巧。

連 path (含檔名) 都忽略的技巧十分好用，也就是當在同一個頁面中要指定不同的 QueryString 參數時，我就會用此技巧，範例如下：

```
# 跳到第 2 頁
<a href="?pageNo=2">第 2 頁</a>

# 變更 sortby 參數的值
<a href="?sortby=filesize">File Size</a>
```

**技巧 3：忽略 scheme 與 authority 與 path 與 query 部分**

此技巧也就是所謂的「頁內連結」或「書籤」，不算是技巧，是一種常見的表示法。最常用的地方就是在頁面中加上「回頁首」功能，範例如下：

```
<a href="#top">Top</a>
```

當頁面中找不到 **top** 這個「書籤」時，預設就會跳到本頁的最上方。

**技巧 4：僅忽略 scheme 的部分**

此法比較少見，但十分適用於網站內經常遊走於 HTTP 與 HTTPS 之間的網頁。

一般較大型的網站，會將網站內的圖片、影片、CSS、或 JavaScript 檔案統一放置在不同主機或不同網域下，以縮短網頁載入的時間（相關技巧可參照我之前寫的 [加速前端網頁效能的14條規則](/post/2007/11/24/14-rules-for-faster-front-end-performance-notes) 文章），通常這類的寫法會撰寫完整的「絕對路徑」，例如 [Yahoo! 奇摩](http://tw.yahoo.com/) 的首頁 ( [http://tw.yahoo.com/](http://tw.yahoo.com/) ) 的 Logo 圖檔 ( http://l.yimg.com/tw.yimg.com/i/tw/hp/spirit/yahoo\_logo.gif ) 就放在不同的網域下。

若我們假設今天 **http://tw.yahoo.com/** 網址將改成 **https://tw.yahoo.com/** 時，若頁面內的圖檔網址一樣是 http:// 開頭的網址時，使用者的瀏覽器就會出現「這個畫面同時含有安全性與非安全性的項目。要顯示非安全性項目？」的警示訊息，如下圖示(以 IE 為例)：

![安全性資訊 :: 這個畫面同時含有安全性與非安全性的項目。要顯示非安全性項目？](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/1a76a6f070bc4107fdce-image_8.png)

一般較講究安全的網站，會在進行會員登入、註冊、或進行線上刷卡時，特別將網址轉向到 https 頁面（SSL），這是因為使用 SSL 連線對伺服器會造成一定程度的負擔，所以通常只會在傳輸重要資料時才會進行 SSL 加密連線，但這時網站中的所有圖檔若不在同一台主機時就可以套用此技巧，如下範例：

```
<img src="//l.yimg.com/tw.yimg.com/i/tw/hp/spirit/yahoo_logo.gif" />
```

這時若你連到的網頁是 **https://tw.yahoo.com/** 時，當讀取圖檔時也會預設採用 https 這個 scheme，這樣就不會產生「安全性資訊」的警示訊息了。 若以此範例來說，你的 **l.yimg.com** 主機當然也要啟用 HTTPS 功能以及安裝 SSL 憑證，否則還是一樣會抓不到圖片的。

**結語**

由此可見，網址從最右邊的 query 部分一直到 authority 部分都是可以省略的，唯一的限制是不能「跳著省略」，例如說你不能同時省略 scheme 與  path 部分。而省略過的網址就稱為「**相對網址**」。

今天講「網址」這種超級基礎的知識，相信還是有些人會覺得這個「小技巧」很新鮮。我時常跟我帶的人說：「**擁有實務經驗十分重要，但若不懂得技術原理，成長的力道就會受限**」。身為一個研發人員，不斷進修本來就是我們的宿命，除了平時要經常寫 Code 以外，花點時間看書是有必要的！

常言道：「書到用時方恨少」，所有人都知道這個道理，但又有多少人能夠身體力行呢？也許是因為工作忙碌沒時間進修，但這真的可以當藉口嗎？

**相關連結**

-   [RFC 3986: Uniform Resource Identifier (URI): Generic Syntax](http://tools.ietf.org/html/rfc3986)
-   [Uniform Resource Locator - Wikipedia](http://en.wikipedia.org/wiki/Uniform_Resource_Locator)
-   [Uniform Resource Identifier - Wikipedia](http://en.wikipedia.org/wiki/Uniform_Resource_Identifier)
-   [Uniform Resource Name - Wikipedia](http://en.wikipedia.org/wiki/Uniform_Resource_Name)
-   [URL normalization - Wikipedia](http://en.wikipedia.org/wiki/URL_normalization)
-   《遠見雜誌》在 2007 年 8 月號的閱讀大調查報告（只有 41.7% 的 18 歲以上的民眾有看書習慣）
