?
This document uses PHP Chinese website manual Release
一個(gè)代理服務(wù)器自動(dòng)配置(PAC)文件是一個(gè)JavaScript函數(shù),確定網(wǎng)絡(luò)瀏覽器的請(qǐng)求(HTTP,HTTPS和FTP)是否直接去目的地或轉(zhuǎn)發(fā)到Web代理服務(wù)器。包含在PAC文件中的JavaScript函數(shù)定義了這個(gè)函數(shù):
function FindProxyForURL(url, host){ // ...} ret = FindProxyForURL(url, host);
function FindProxyForURL(url, host)
url正在訪問(wèn)的URL。https://
URL 的路徑和查詢組件被剝離。在Chrome中,您可以通過(guò)設(shè)置PacHttpsUrlStrippingEnabled
為禁用此功能false
,在Firefox中,首選項(xiàng)是network.proxy.autoconfig_url.include_path
.host從URL中提取的主機(jī)名。這只是為了方便; 它與之間://和第一個(gè):/之后是相同的字符串。端口號(hào)不包含在此參數(shù)中。它可以在必要時(shí)從URL中提取。
返回描述配置的字符串。該字符串的格式在下面的返回值格式中定義。
JavaScript函數(shù)返回單個(gè)字符串
如果字符串為空,則不應(yīng)使用代理
該字符串可以包含任意數(shù)量的以分號(hào)分隔的構(gòu)建塊:
DIRECTConnections應(yīng)直接進(jìn)行,而不使用任何代理PROXY _host:port_應(yīng)使用指定的代理SOCKS _host:port_應(yīng)使用指定的SOCKS服務(wù)器
最近的Firefox支持版本也是這樣:
HTTP_host:port_應(yīng)使用指定的代理HTTP_host:port_應(yīng)使用指定的HTTPS代理SOCKS4_host:port_SOCKS5_host:port_應(yīng)使用指定的SOCKS服務(wù)器(具有指定的SOCK版本)
如果有多個(gè)以分號(hào)分隔的設(shè)置,則將使用最左側(cè)的設(shè)置,直到Firefox無(wú)法建立與代理的連接。在那種情況下,下一個(gè)值將被使用,等等。
30分鐘后,瀏覽器將自動(dòng)重試以前無(wú)響應(yīng)的代理。額外的嘗試將在一小時(shí)后開始,總是在兩次嘗試之間增加30分鐘。
如果所有代理都關(guān)閉,并且沒有指定DIRECT選項(xiàng),瀏覽器將詢問(wèn)是否應(yīng)暫時(shí)忽略代理,并嘗試直接連接。20分鐘后,瀏覽器會(huì)詢問(wèn)代理是否應(yīng)該重試,再過(guò)40分鐘后再詢問(wèn)。查詢將繼續(xù),總是在查詢之間經(jīng)過(guò)的時(shí)間增加20分鐘。
PROXY w3proxy.netscape.com:8080; PROXY mozilla.netscape.com:8081一級(jí)代理是w3proxy:8080; 如果發(fā)生故障,開始使用mozilla:8081,直到主代理再次出現(xiàn)。PROXY w3proxy.netscape.com:8080; PROXY mozilla.netscape.com:8081; DIRECTSame如上所述,但是如果兩個(gè)代理都關(guān)閉了,自動(dòng)開始直接連接。(在上面的第一個(gè)例子中,Netscape會(huì)詢問(wèn)用戶確認(rèn)是否有直接連接;在這種情況下,沒有用戶干預(yù)。)PROXY w3proxy.netscape.com:8080; SOCKS socks:如果主代理服務(wù)器關(guān)閉,則使用SOCKS。
自動(dòng)配置文件應(yīng)該保存到一個(gè)帶有.pac文件擴(kuò)展名的文件中:
proxy.pac
而MIME類型設(shè)置為:
application/x-ns-proxy-autoconfig
接下來(lái),您應(yīng)該配置服務(wù)器將.pac文件擴(kuò)展名映射到MIME類型。
筆記:
JavaScript函數(shù)應(yīng)該總是保存到文件中,而不是嵌入到HTML中。
本文末尾的示例已完成。沒有其他語(yǔ)法需要將其保存到文件中并使用它。(當(dāng)然,必須編輯JavaScript以反映您的網(wǎng)站的域名和/或子網(wǎng)。)
這些函數(shù)可用于構(gòu)建PAC文件:
Hostname based conditions
isPlainHostName()(about:blank#isPlainHostName(%29)
dnsDomainIs()(about:blank#dnsDomainIs(host,%20domain%29)
localHostOrDomainIs()(about:blank#localHostOrDomainIs(host,%20hostdom%29)
isResolvable()(about:blank#isResolvable(host%29)
isInNet()(about:blank#isInNet(host,%20pattern,%20mask%29)
Related utility functions
dnsResolve()(about:blank#dnsResolve(host%29)
convert_addr()(about:blank#convert_addr(%29)
myIpAddress()(about:blank#myIpAddress(%29)
dnsDomainLevels()(about:blank#dnsDomainLevels(host%29)
URL/hostname based conditions
shExpMatch()(about:blank#shExpMatch(str,%20shexp%29)
Time based conditions
weekdayRange()(about:blank#weekdayRange(wd1,%20wd2,%20gmt%29)
dateRange()(about:blank#dateRange(%29)
timeRange()(about:blank#timeRange(%29)
There is one associative array already defined (because a JavaScript currently cannot define them on its own):
ProxyConfig.bindings
注意: pactester(pacparser包的一部分)用于測(cè)試以下語(yǔ)法示例。
The PAC file is named proxy.pac
Command line: pactester -p ~/pacparser-master/tests/proxy.pac -u http://www.mozilla.org
This command passes the
host
parameter www.mozilla.org and the
url
parameter http://www.mozilla.org.
isPlainHostName(host)
主機(jī)URL中的主機(jī)名(不包括端口號(hào))。
當(dāng)且僅當(dāng)主機(jī)名中沒有域名(無(wú)點(diǎn))時(shí)才為真。
function FindProxyForURL(url, host) { if (!isPlainHostName(host)) return host;}//returns "www.mozilla.org"
function FindProxyForURL(url, host) { if (isPlainHostName("www")) return "isPlainHostName is true"; return "isPlainHostName is false";}//returns "isPlainHostName is true"
dnsDomainIs(host, domain)
主機(jī)是來(lái)自URL的主機(jī)名。域用來(lái)測(cè)試主機(jī)名。
當(dāng)且僅當(dāng)主機(jī)名的域匹配時(shí)返回true。
function FindProxyForURL(url, host) { if (dnsDomainIs("www.mozilla.org", ".mozilla.org")) return "dnsDomainIs is true"; return "dnsDomainIs is false";}//returns "dnsDomainIs is true"
function FindProxyForURL(url, host) { if (dnsDomainIs("www", ".mozilla.org")) return "dnsDomainIs is true"; return "dnsDomainIs is false";}//returns "dnsDomainIs is false"
localHostOrDomainIs(host, hostdom)
hosthost從URL.hostdomFully限定的主機(jī)名中匹配的主機(jī)名。
如果主機(jī)名與指定的主機(jī)名完全匹配,或者主機(jī)名中沒有域名部分,但未匹配的主機(jī)名匹配,則為true。
function FindProxyForURL(url, host) { if (localHostOrDomainIs("www.mozilla.org", "www.mozilla.org")) return "localHostOrDomainIs is true (exact match)"; return "localHostOrDomainIs is false";}//returns "localHostOrDomainIs is true (exact match)"
function FindProxyForURL(url, host) { if (localHostOrDomainIs("www", "www.mozilla.org")) return "localHostOrDomainIs is true (hostname match, domain not specified))"; return "localHostOrDomainIs is false";}//returns "localHostOrDomainIs is true (hostname match, domain not specified))"
function FindProxyForURL(url, host) { if (localHostOrDomainIs("www.google.com", "www.mozilla.org")) return "localHostOrDomainIs is true"; return "localHostOrDomainIs is false (domain name mismatch)";} // returns "localHostOrDomainIs is false (domain name mismatch)"
function FindProxyForURL(url, host) { if (localHostOrDomainIs("home.mozilla.org", "www.mozilla.org")) return "localHostOrDomainIs is true"; return "localHostOrDomainIs is false (domain name mismatch)"; }// returns "localHostOrDomainIs is false (hostname mismatch)"
isResolvable(host)
hostis是URL中的主機(jī)名。
嘗試解析主機(jī)名。成功返回true。
function FindProxyForURL(url, host) { if (isResolvable("www.mozilla.org")) return "isResolvable is true"; return "isResolvable is false";}// returns "isResolvable is true"
isInNet(host, pattern, mask)
hosta DNS主機(jī)名或IP地址。如果一個(gè)主機(jī)名被傳遞,它將通過(guò)這個(gè)函數(shù)被解析為一個(gè)IP地址。在IP地址模式中用點(diǎn)分隔的格式.maskmask表示IP地址模式,通知應(yīng)匹配IP地址的哪些部分。0表示忽略,255表示匹配。
當(dāng)且僅當(dāng)主機(jī)的IP地址與指定的IP地址模式匹配時(shí)才為真。
模式和模板規(guī)范的完成方式與SOCKS配置相同。
function FindProxyForURL(url, host) {// put in the address returned by dnsResolve (see next example) if (isInNet(host, "63.245.213.24", "255.255.255.255")) return "isInNet is true"; return "isInNet is false";}// returns "isInNet is true"
dnsResolve(host)
hosthostname來(lái)解決。
將給定的DNS主機(jī)名解析為IP地址,并以點(diǎn)分隔格式將其作為字符串返回。
function FindProxyForURL(url, host) { return dnsResolve("www.mozilla.org");} //returns the string "104.16.41.2"
convert_addr(ipaddr)
ipaddrAny虛線地址,如IP地址或掩碼。
將四個(gè)點(diǎn)分隔的字節(jié)連接成一個(gè)4字節(jié)的字并將其轉(zhuǎn)換為十進(jìn)制。
function FindProxyForURL(url, host) { return convert_addr("104.16.41.2");} //returns the decimal number 1745889538
myIpAddress()
(none)
以點(diǎn)分隔的整數(shù)格式返回運(yùn)行Firefox的計(jì)算機(jī)的服務(wù)器IP地址,作為字符串。
myIpAddress()返回與nslookup localhost
Linux機(jī)器返回的服務(wù)器地址相同的IP地址。它不返回公共IP地址。
function FindProxyForURL(url, host) { return myIpAddress();} //returns the string "127.0.1.1" if you were running Firefox on that localhost
dnsDomainLevels(host)
hostis是URL中的主機(jī)名。
返回主機(jī)名中的DNS域級(jí)別(點(diǎn)數(shù))的數(shù)量(整數(shù))。
function FindProxyForURL(url, host) { return dnsDomainLevels("www");}//returns 0
function FindProxyForURL(url, host) { return dnsDomainLevels("mozilla.org");}//returns 1
function FindProxyForURL(url, host) { return dnsDomainLevels("www.mozilla.org");}//returns 2
shExpMatch(str, shexp)
stris要比較的任何字符串(例如,URL或主機(jī)名).shexp是一個(gè)shell表達(dá)式來(lái)比較。
如果字符串匹配指定的shell表達(dá)式,則返回true。
目前,這些模式是 shell表達(dá)式,而不是正則表達(dá)式。
function FindProxyForURL(url, host) { return shExpMatch("http://home.netscape.com/people/ari/index.html", "*/ari/*");}//returns true
function FindProxyForURL(url, host) { return shExpMatch("http://home.netscape.com/people/montulli/index.html", "*/ari/*");}//returns false
weekdayRange(wd1, wd2, gmt)
注意:(在Firefox 49之前)如果您希望函數(shù)將這些參數(shù)作為范圍進(jìn)行評(píng)估,則wd1必須小于wd2??吹较旅娴木?。
有序周日字符串的wd1和wd2One:
"SUN"|"MON"|"TUE"|"WED"|"THU"|"FRI"|"SAT"
gmtI字符串“GMT”或被忽略。
只有第一個(gè)參數(shù)是強(qiáng)制性的。第二,第三或兩者都可能被排除在外。
如果僅存在一個(gè)參數(shù),則該函數(shù)在參數(shù)代表的星期幾返回true值。如果將字符串“GMT”指定為第二個(gè)參數(shù),則時(shí)間取為GMT。否則,他們被認(rèn)為是在當(dāng)?shù)氐臅r(shí)區(qū)。
如果wd1和wd1都已定義,則當(dāng)前工作日在兩個(gè)有序工作日之間時(shí),條件為真。界限是包容性的,但界限是有序的。如果指定了“GMT”參數(shù),則時(shí)間取為GMT。否則,使用本地時(shí)區(qū)。
日子的順序很重要 ; 在Firefox 49之前,總是會(huì)評(píng)估為真?,F(xiàn)在只會(huì)在當(dāng)前日期為星期三或星期日的情況下評(píng)估為真。weekdayRange("SUN", "SAT")weekdayRange("WED", "SUN")
function FindProxyForURL(url, host) { return weekdayRange("MON", "FRI");}//returns true Monday through Friday (local timezone)
function FindProxyForURL(url, host) { return weekdayRange("MON", "FRI", "GMT");}//returns true Monday through Friday (GMT timezone)
function FindProxyForURL(url, host) { return weekdayRange("SAT");}//returns true true on Saturdays local time
function FindProxyForURL(url, host) { return weekdayRange("SAT", "GMT");}//returns true on Saturdays GMT time
function FindProxyForURL(url, host) { return weekdayRange("FRI", "MON");}//returns true Friday and Monday only (note, order does matter!)
dateRange(<day1>, <month1>, <year1>, <day2>, <month2>, <year2>, <gmt>)
注意:(在Firefox 49之前)如果您希望函數(shù)將這些參數(shù)評(píng)估為范圍,則day1必須小于day2,month1必須小于month2,并且year1必須小于year2。看到下面的警告。
day是1到31之間的月份的有序日期(作為整數(shù))。
1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31
月是下面的有序月份字符串之一。
"JAN"|"FEB"|"MAR"|"APR"|"MAY"|"JUN"|"JUL"|"AUG"|"SEP"|"OCT"|"NOV"|"DEC"
年是訂購(gòu)的全年整數(shù)。例如,2016(不是 16).gmt是字符串“GMT”,它在GMT時(shí)區(qū)中進(jìn)行時(shí)間比較,或者被忽略。如果沒有指定,時(shí)間將被視為在當(dāng)?shù)貢r(shí)區(qū)。
如果只指定了一個(gè)值(來(lái)自每個(gè)類別:日,月,年),則該函數(shù)僅在符合該規(guī)范的日期才返回真值。如果同時(shí)指定了這兩個(gè)值,則結(jié)果在這些時(shí)間之間為真,包括邊界,但邊界是有序的。
日期,月份和年份的順序很重要 ; 在Firefox 49之前,會(huì)一直評(píng)估為。如果當(dāng)前月份是12月或1月,現(xiàn)在只會(huì)評(píng)估為真。dateRange("JAN", "DEC")truedateRange("DEC", "JAN")
function FindProxyForURL(url, host) { return dateRange(1);}//returns true on the first day of each month, local timezone
function FindProxyForURL(url, host) { return dateRange(1, "GMT")}//returns true on the first day of each month, GMT timezone
function FindProxyForURL(url, host) { return dateRange(1, 15);}//returns true on the first half of each month
function FindProxyForURL(url, host) { return dateRange(24, "DEC");}//returns true on 24th of December each year
function FindProxyForURL(url, host) { return dateRange("JAN", "MAR");}//returns true on the first quarter of the year
function FindProxyForURL(url, host) { return dateRange(1, "JUN", 15, "AUG");}//returns true from June 1st until August 15th, each year (including June 1st and August 15th)
function FindProxyForURL(url, host) { return dateRange(1, "JUN", 1995, 15, "AUG", 1995);}//returns true from June 1st, 1995, until August 15th, same year
function FindProxyForURL(url, host) { return dateRange("OCT", 1995, "MAR", 1996);}//returns true from October 1995 until March 1996 (including the entire month of October 1995 and March 1996)
function FindProxyForURL(url, host) { return dateRange(1995);}//returns true during the entire year of 1995
function FindProxyForURL(url, host) { return dateRange(1995, 1997);}//returns true from beginning of year 1995 until the end of year 1997
timeRange(<hour1>, <min1>, <sec1>, <hour2>, <min2>, <sec2>, <gmt>)
注意:(在Firefox 49之前)如果希望函數(shù)將這些參數(shù)評(píng)估為范圍,則類別hour1,min1,sec1必須小于類別hour2,min2,sec2??吹较旅娴木?。
hour是0到23之間的小時(shí)。(0是午夜,23是晚上11點(diǎn)。)minMinutes從0到59.secSeconds從0到59.gmt GMT或時(shí)區(qū)字符串“GMT”,或未指定,用于本地時(shí)區(qū)。
如果只指定了一個(gè)值(來(lái)自每個(gè)類別:小時(shí),分鐘,秒),則該函數(shù)僅在符合該規(guī)范的時(shí)候返回真值。如果同時(shí)指定了這兩個(gè)值,則結(jié)果在這些時(shí)間之間為真,包括邊界,但邊界是有序的。
小時(shí),分鐘,秒的順序 ; 在Firefox 49之前,總是會(huì)評(píng)估為真?,F(xiàn)在只會(huì)在當(dāng)前時(shí)間為23:00或午夜時(shí)評(píng)估為真。timeRange(0, 23)timeRange(23, 0)
function FindProxyForURL(url, host) { return timerange(12);}//returns true from noon to 1pm
function FindProxyForURL(url, host) { return timerange(12, 13);}//returns true from noon to 1pm
function FindProxyForURL(url, host) { return timerange(12, "GMT");}//true from noon to 1pm, in GMT timezone
function FindProxyForURL(url, host) { return timerange(9, 17);}//returns true from 9am to 5pm
function FindProxyForURL(url, host) { return timerange(8, 30, 17, 00);}//returns true from 8:30am to 5:00pm
function FindProxyForURL(url, host) { return timerange(0, 0, 0, 0, 0, 30);}//returns true between midnight and 30 seconds past midnight
注意:由于以下所有示例都非常具體,因此尚未經(jīng)過(guò)測(cè)試。
所有未完全限定的主機(jī)或者本地域中的主機(jī)都將直接連接。其他一切都將通過(guò)w3proxy:8080。如果代理服務(wù)器關(guān)閉,連接將自動(dòng)變?yōu)橹苯舆B接:
function FindProxyForURL(url, host) { if (isPlainHostName(host) || dnsDomainIs(host, ".mozilla.org")) { return "DIRECT"; } else { return "PROXY w3proxy.mozilla.org:8080; DIRECT"; }}
注意:對(duì)于只有一個(gè)代理的情況,這是最簡(jiǎn)單和最有效的autoconfig文件。
如果存在屬于本地域但位于防火墻之外且只能通過(guò)代理服務(wù)器訪問(wèn)的主機(jī)(如主Web服務(wù)器),則可以使用以下localHostOrDomainIs()
函數(shù)處理這些異常:
function FindProxyForURL(url, host) { if ((isPlainHostName(host) || dnsDomainIs(host, ".mozilla.org")) && !localHostOrDomainIs(host, "www.mozilla.org") && !localHostOrDoaminIs(host, "merchant.mozilla.org")) { return "DIRECT"; } else { return "PROXY w3proxy.mozilla.org:8080; DIRECT"; }}
上述示例將使用代理服務(wù)器,除mozilla.org域中的本地主機(jī)以外的所有其他服務(wù)器,但主機(jī)www.mozilla.org和merchant.mozilla.org將通過(guò)代理服務(wù)器的情況進(jìn)一步例外。
請(qǐng)注意以上效率的例外順序:localHostOrDomainIs()函數(shù)僅針對(duì)本地域中的URL執(zhí)行,而不是針對(duì)每個(gè)URL執(zhí)行。注意在和表達(dá)式之前的或表達(dá)式的圓括號(hào),以實(shí)現(xiàn)上述有效行為。
此示例適用于內(nèi)部DNS服務(wù)器設(shè)置為只能解析內(nèi)部主機(jī)名的環(huán)境,目標(biāo)是僅為不可解析的主機(jī)使用代理:
function FindProxyForURL(url, host) { if (isResolvable(host)) return "DIRECT"; else return "PROXY proxy.mydomain.com:8080";}
以上需要每次查詢DNS; 它可以與其他規(guī)則進(jìn)行智能分組,以便僅在其他規(guī)則不產(chǎn)生結(jié)果時(shí)才咨詢DNS:
function FindProxyForURL(url, host) { if (isPlainHostName(host) || dnsDomainIs(host, ".mydomain.com") || isResolvable(host)) { return "DIRECT"; } else { return "PROXY proxy.mydomain.com:8080"; }}
在這個(gè)例子中,給定子網(wǎng)中的所有主機(jī)直接連接,其他連接通過(guò)代理連接:
function FindProxyForURL(url, host) { if (isInNet(host, "198.95.0.0", "255.255.0.0")) return "DIRECT"; else return "PROXY proxy.mydomain.com:8080";}
同樣,通過(guò)在開始時(shí)添加冗余規(guī)則,可以最大限度地減少上述DNS服務(wù)器的使用:
function FindProxyForURL(url, host) { if (isPlainHostName(host) || dnsDomainIs(host, ".mydomain.com") || isInNet(host, "198.95.0.0", "255.255.0.0")) { return "DIRECT"; } else { return "PROXY proxy.mydomain.com:8080"; }}
這個(gè)例子更復(fù)雜。有四(4)個(gè)代理服務(wù)器; 其中一個(gè)對(duì)所有其他人來(lái)說(shuō)都是一個(gè)熱門候補(bǔ),所以如果其余三個(gè)中的任何一個(gè)倒下,第四個(gè)將會(huì)接管。此外,剩余的三臺(tái)代理服務(wù)器根據(jù)URL模式共享負(fù)載,這使得它們的緩存更加有效(三臺(tái)服務(wù)器上只有一個(gè)文檔副本 - 而不是每個(gè)副本上的副本)。負(fù)載分布如下:
Proxy | Purpose |
---|---|
#1 | .com domain |
#2 | .edu domain |
#3 | all other domains |
#4 | hot stand-by |
所有本地訪問(wèn)都希望是直接的。所有代理服務(wù)器都在端口8080上運(yùn)行(它們不需要)。請(qǐng)注意字符串如何與JavaScript中的+運(yùn)算符連接。
function FindProxyForURL(url, host) { if (isPlainHostName(host) || dnsDomainIs(host, ".mydomain.com")) return "DIRECT"; else if (shExpMatch(host, "*.com")) return "PROXY proxy1.mydomain.com:8080; " + "PROXY proxy4.mydomain.com:8080"; else if (shExpMatch(host, "*.edu")) return "PROXY proxy2.mydomain.com:8080; " + "PROXY proxy4.mydomain.com:8080"; else return "PROXY proxy3.mydomain.com:8080; " + "PROXY proxy4.mydomain.com:8080";}
大多數(shù)標(biāo)準(zhǔn)的JavaScript功能可用于FindProxyForURL()函數(shù)。例如,要根據(jù)協(xié)議設(shè)置不同的代理,可以使用substring()函數(shù):
function FindProxyForURL(url, host) { if (url.substring(0, 5) == "http:") { return "PROXY http-proxy.mydomain.com:8080"; } else if (url.substring(0, 4) == "ftp:") { return "PROXY ftp-proxy.mydomain.com:8080"; } else if (url.substring(0, 7) == "gopher:") { return "PROXY gopher-proxy.mydomain.com:8080"; } else if (url.substring(0, 6) == "https:" || url.substring(0, 6) == "snews:") { return "PROXY security-proxy.mydomain.com:8080"; } else { return "DIRECT"; } }
注意:使用前面介紹的shExpMatch()函數(shù)可以完成相同的操作。
例如:
// ...if (shExpMatch(url, "http:*")) { return "PROXY http-proxy.mydomain.com:8080;}// ...
自動(dòng)配置文件可以由CGI腳本輸出。例如,當(dāng)根據(jù)客戶端IP地址(CGI中的REMOTE_ADDR環(huán)境變量)使自動(dòng)配置文件的行為不同時(shí),這很有用。
使用isInNet()
,isResolvable()
和dnsResolve()
功能應(yīng)該仔細(xì)考慮,因?yàn)樗鼈冃枰蛔稍兊腄NS服務(wù)器。所有其他與自動(dòng)配置相關(guān)的功能都是單純的字符串匹配功能,不需要使用DNS服務(wù)器。如果使用代理服務(wù)器,代理服務(wù)器將執(zhí)行其DNS查找,這將使DNS服務(wù)器的影響加倍。大多數(shù)情況下,這些功能對(duì)于達(dá)到預(yù)期效果并不是必需的。
在MDN上編輯此頁(yè)(https://developer.mozilla.org/en-US/docs/Web/HTTP/Proxy servers_and_tunneling / Proxy_Auto-Configuration(PAC%29_file $ edit)