Proxy.pac:自動組態設定檔/自動設定網址 Proxy Autoconfig
原文:
http://wp.netscape.com/eng/mozilla/2.0/relnotes/demo/proxy-live.html
(譯註:這份文件可能很舊,但大部分內容應該還是適用,我簡單翻譯+整理如下)
翻譯摘要如下:
[hr]
Proxy 自動組態設定檔(Proxy AutoConfig File)是由 Javascript 檔寫成,可以放在本地或遠端
自動組態設定檔必須包含此 function
代碼:
function FindProxyForURL(url, host)
{
...
}
當所有 URL 在存取時,若有設定「自動組態設定檔」,便執行此 fucntion,獲得回傳值
代碼:
ret = FindProxyForURL(url, host);
這裡的 URL 是瀏覽器網址 URL
這裡的 host 是由 URL 所取出的 hostname
這裡的 ret 是回傳值,描述處理後的值
[hr]
自動組態設定檔格式與 MIME 設定
1. 副檔名通常是 .pac,通常我們會取名為 proxy.pac 或 autoproxy.pac
2. 部份的伺服器需要針對 .pac 設定適當的 MIME Type Mapping
如:application/x-ns-proxy-autoconfig
[hr]
回傳格式
1. 回傳 ret 的值是字串
2. 若 ret 的字串是 NULL,瀏覽器就不需處理,直接連結
3. 回傳的字串分成下列三種分類:
(a) DIRECT => 代表直接連結
(b) PROXY host:port => 代表應該使用指定的 host 和 port 作為此 URL 的 Proxy Server
(c) SOCKS host:port => 代表應該使用指定的 host 和 port 作為此 URL 的 SOCKS4/5 Server
若回傳的 PROXY host:port 有多筆,則瀏覽器會先由第一筆開始嘗試連結,
若失敗,接著第二筆...。
例如:
代碼:
PROXY proxy.vovo2000.com:8080; PROXY proxy2.vovo2000.com:8080
代表 會先用 proxy.vovo2000.com,如果該 proxy 失效,則連結 proxy2.vovo2000.com
代碼:
PROXY proxy.vovo2000.com:8080; PROXY proxy2.vovo2000.com:8080; DIRECT
同上面的例子,但是如果前兩個 proxy 都無法使用,則直接連結(DIRECT)
[hr]
下面是幾個 Javascirpt Function 可用於 Proxy.pac 自動組態設定檔
代碼:
* Hostname 相關函式
- isPlainHostName()
- dnsDomainIs()
- localHostOrDomainIs()
- isResolvable()
- isInNet()
* 相關 DNS/IP 工具函式
- dnsResolve()
- myIpAddress()
- dnsDomainLevels()
* URL/hostname 相關相關函式
- shExpMatch()
* 時間函式
- weekdayRange()
- dateRange()
- timeRange()
* Bindings
- ProxyConfig.bindings
isPlainHostName(host)
@host: URL 內的「純」hostname (no port #)
範例:
代碼:
isPlainHostName("www")
=> 回傳 true.
代碼:
isPlainHostName("www.vovo2000.com")
=> 回傳 false
dnsDomainIs(host, domain)
@host: hostname
@domain: domain name 是否是 hostname 的 domain
代碼:
dnsDomainIs("www.vovo2000.com", ".vovo2000.com")
=> 回傳 true.
代碼:
dnsDomainIs("www", ".vovo2000.com")
dnsDomainIs("www.microsoft.com", ".vovo2000.com.com")
=> 這兩者都是 false
localHostOrDomainIs(host, hostdom)
@host: hostname
@hostdom: 代測試 hostdom
回傳 True 如果: (a) host == hostdom (b) host 為 nodomain-name 的 hostname 且 match hostdom
代碼:
localHostOrDomainIs("www.vovo2000.com", "www.vovo2000.com")
localHostOrDomainIs("www", "www.vovo2000.com")
localHostOrDomainIs("www.microsoft.com", "www.vovo2000.com")
localHostOrDomainIs("mail.vovo2000.com", "www.vovo2000.com")
=> 前兩者 True, 後兩者 false
isResolvable(host)
@host: hostname from URL
代碼:
isResolvable("vovo2000.com")
isResolvable("nonohihijaja1234.vovo2000.mars")
=> 看 DNS 是否可以解析 hostname:前者 true。後者大概火星才找的到 false 回傳
isInNet(host, pattern, mask)
@host: DNS hostname 或 IP address
@pattern: IP Address 格式
@mask: IP Address Mask, 0: ignore, 255 match
簡單的來說就是看是否 host 在 pattern + mask 的定義範圍內
host 可為 hostname 或 ip address
代碼:
isInNet(host, "198.95.249.79", "255.255.255.255")
=> 如果 host 是 198.95.249.79 則回傳 true
代碼:
isInNet(host, "198.95.0.0", "255.255.0.0")
=> 如果 host 是 198.95.*.* 則回傳 true
dnsResolve(host)
@host: hostname
轉 hostname 為 IP address
代碼:
dnsResolve("vovo2000.com")
=> 回傳 210.66.XXX.XXX
myIpAddress()
回傳瀏覽器所執行的 IP Address
代碼:
myIpAddress()
=> 回傳您的 IP Address
dnsDomainLevels(host)
@host: hostname
回傳 hostname 有幾個 dot(domain name level)
代碼:
dnsDomainLevels("www")
dnsDomainLevels("mail.vovo2000.com")
=> 分別回傳 0 和 2
shExpMatch(str, shexp)
@str: URL/hostname 字串
@shexp: Shell Express 比較 pattern
看是否 URL/hostname == shexp
代碼:
shExpMatch("http://vovo2000.com/paintbbs/", "*/paintbbs/*")
=> 因為 hostname 有 /paintbbs/ 所以回傳 true
代碼:
shExpMatch("http://vovo2000.com/paintchat/", "*/paintbbs/*")
=> hostname 沒有 /paintbbs/ 回傳 flase
weekdayRange(wd1, wd2, gmt)
@wd1: SUN MON TUE WED THU FRI SAT 七個 week day(必要欄位)
@wd2: SUN MON TUE WED THU FRI SAT 七個 week day(非必要欄位)
@gmt: GMT 或空白 (非必要欄位),此欄位若不定義則為本地時區
判斷「目前時間」是否在此 Range 內
代碼:
weekdayRange("MON", "FRI")
weekdayRange("MON", "FRI", "GMT")
weekdayRange("SAT")
weekdayRange("SAT", "GMT")
weekdayRange("FRI", "MON")
=> return true 如果在上述時間範圍內,適用於「以 weekday」為範圍的日期判斷
dateRange(day)
dateRange(day1, day2)
dateRange(mon)
dateRange(month1, month2)
dateRange(year)
dateRange(year1, year2)
dateRange(day1, month1, day2, month2)
dateRange(month1, year1, month2, year2)
dateRange(day1, month1, year1, day2, month2, year2)
dateRange(day1, month1, year1, day2, month2, year2, gmt)
@day: 日 1~31
@month: 月 JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC
@year: 年,必須為四位數 e.g. 2007
@gmt: GMT 或 localtime
一樣是作為日期判斷,但是可明確指出「年、月、日」範圍
範例:
代碼:
dateRange(1)
dateRange(1, "GMT")
dateRange(1, 15)
dateRange(24, "DEC")
dateRange(24, "DEC", 2007)
dateRange("JAN", "MAR")
dateRange(1, "JUN", 15, "AUG")
dateRange(1, "JUN", 15, 2007, "AUG", 2007)
dateRange("OCT", 2006, "MAR", 2007)
dateRange(2007)
dateRange(2006, 2007)
timeRange(hour)
timeRange(hour1, hour2)
timeRange(hour1, min1, hour2, min2)
timeRange(hour1, min1, sec1, hour2, min2, sec2)
timeRange(hour1, min1, sec1, hour2, min2, sec2, gmt)
@hour: 小時 0~23 (0 是午夜 12:00)
@min: 分鐘 0~59
@sec: 秒 0~59
@gmt: GMT 或 localtime
利用 timeRange 和 weekdayRange / dateRange 可精確定義出時間
範例:
代碼:
timerange(12)
timerange(12, 13)
timerange(12, "GMT")
timerange(9, 17)
timerange(8, 30, 17, 00)
timerange(0, 0, 0, 0, 0, 30)
[hr]
[hr]
範例 1:如果 *.vovo2000.com 相關的網址則直接連結,其他網址都使用 proxy.vovo2000.com 來連線
代碼:
function FindProxyForURL(url, host)
{
if (isPlainHostName(host) ||
dnsDomainIs(host, ".vovo2000.com"))
return "DIRECT";
else
return "PROXY proxy.vovo2000.com:8080; DIRECT";
}
範例 1b:同範例 1,但如果 local 的 host 是 FTP 和 mail,則還是要透過 Proxy
代碼:
function FindProxyForURL(url, host)
{
if ((isPlainHostName(host) ||
dnsDomainIs(host, ".vovo2000.com")) &&
!localHostOrDomainIs(host, "mail.vovo2000.com") &&
!localHostOrDoaminIs(host, "ftp.vovo2000.com"))
return "DIRECT";
else
return "PROXY proxy.vovo2000.com:8080; DIRECT";
}
範例 2:除非 DNS 無法解析這個 hostname,否則都直接連;無法解析的都透過 proxy
代碼:
function FindProxyForURL(url, host)
{
if (isResolvable(host))
return "DIRECT";
else
return "PROXY proxy.vovo2000.com:8080";
}
範例 2a:上面這種可能每次都要 query DNS,可透過一些 rule combo 來讓 DNS query 次數減少
代碼:
function FindProxyForURL(url, host)
{
if (isPlainHostName(host) ||
dnsDomainIs(host, ".vovo2000.com") ||
isResolvable(host))
return "DIRECT";
else
return "PROXY proxy.vovo2000.com:8080";
}
範例 3:使用 isInNet 的 Subnet 判斷式,讓 Subnet 198.95.*.* 內的直接連,其他的透過 Proxy
代碼:
function FindProxyForURL(url, host)
{
if (isInNet(host, "198.95.0.0", "255.255.0.0"))
return "DIRECT";
else
return "PROXY proxy.vovo2000.com:8080";
}
範例 3a:配合其他 rule 讓 host 解析次數減少
代碼:
function FindProxyForURL(url, host)
{
if (isPlainHostName(host) ||
dnsDomainIs(host, ".vovo2000.com") ||
isInNet(host, "198.95.0.0", "255.255.0.0"))
return "DIRECT";
else
return "PROXY proxy.vovo2000.com:8080";
}
範例 4:利用 shExpMatch 達成 Proxy Balancing 的功能
代碼:
function FindProxyForURL(url, host)
{
if (isPlainHostName(host) || dnsDomainIs(host, ".vovo2000.com"))
return "DIRECT";
else if (shExpMatch(host, "*.com"))
return "PROXY proxy1.vovo2000.com:8080; " +
"PROXY proxy4.vovo2000.com:8080";
else if (shExpMatch(host, "*.edu"))
return "PROXY proxy2.vovo2000.com:8080; " +
"PROXY proxy4.vovo2000.com:8080";
else
return "PROXY proxy3.vovo2000.com:8080; " +
"PROXY proxy4.vovo2000.com:8080";
}
=> 外部需要 Proxy:如果是 *.com 則用 Proxy1,如果是 *.edu 則用 proxy2,其他 .net/.org./.tw/.jp/.cn/... 則用 proxy3
=> 而 proxy4 是各種 routes 的 backup proxy
=> 這個寫法可以在各個 routes 後面加上 DIRECT,如果 proxy 都失效或需要維護時
範例 5:和範例 4 類似,不過這是用 Protocol 來分類作 Balancing
代碼:
function FindProxyForURL(url, host)
{
if (url.substring(0, 5) == "http:") {
return "PROXY proxy1.vovo2000.com:8080; DIRECT";
}
else if (url.substring(0, 4) == "ftp:") {
return "PROXY proxy2.vovo2000.com:8080; DIRECT";
}
else if (url.substring(0, 4) == "mms:") {
return "PROXY proxy3.vovo2000.com:8080; DIRECT";
}
else if (url.substring(0, 6) == "https:" ||
url.substring(0, 6) == "snews:") {
return "PROXY proxy4.vovo2000.com:8080; DIRECT";
}
else {
return "DIRECT";
}
}
=> HTTP 使用 proxy1,FTP 使用 proxy2,mms 使用 proxy3, https 使用 proxy4
=> 上述的 substring 一樣可用 if (shExpMatch(url, "http:*")) 來達成
提示:
1. AutoConfig Proxy.pac 一樣可用 php/cgi 等方式 output 達成更好的輸出方式(2007-11-19 00:12)