Sun Java System Web Proxy Server 4.0.8 管理指南

手动创建自动配置文件

本节介绍如何手动创建自动配置文件。

代理自动配置文件是使用客户端 JavaScript 编写的。每个文件都包含一个名为 FindProxyForURL() 的 JavaScript 函数,用于确定浏览器应针对每个 URL 使用的代理服务器(如果有)。浏览器会向此 JavaScript 函数发送两个参数:目标原始服务器的主机名以及浏览器尝试获取的 URL。JavaScript 函数将向 Navigator 返回一个值,告知它如何继续执行。以下部分将介绍函数语法以及可能的返回值。

FindProxyForURL() 函数

FindProxyFor() URL 函数的语法如下:

function FindProxyForURL(url, host){   ...}

对于浏览器访问的每个 URL,浏览器都会发送 urlhost 参数,并按如下方式调用此函数:

ret = FindProxyForURL(url, host);

url 是要在浏览器中访问的完整 URL。

host 是从要访问的 URL 中提取的主机名。这样做仅仅是为了方便;它与 :// 和其后的第一个 :/ 之间的字符串相同。此参数中不包括端口号,可根据需要从 URL 中提取它。

ret(返回值)是一个用于描述配置的字符串。

函数返回值

自动配置文件包含函数 FindProxyForURL()。此函数使用客户机主机名以及所访问的 URL 作为参数。此函数将返回一个字符串,告知浏览器如何继续执行。如果字符串为空,则不应使用任何代理。此字符串可以包含下表所示的任意数目的生成块,其间以分号隔开。

表 17–2 FindProxyForURL() 返回值

返回值 

引起的浏览器操作 

DIRECT

不通过任何代理直接与服务器建立连接。 

PROXY host:port

使用指定的代理和端口号。如果存在多个以分号隔开的值,则使用第一个代理。如果此代理失败,则使用下一个代理,依此类推。 

SOCKS host:port

使用指定的 SOCKS 服务器。如果存在多个以分号隔开的值,则使用第一个代理。如果此代理失败,则使用下一个代理,依此类推。 

如果浏览器遇到不可用的代理服务器,则浏览器将每隔 30 分钟自动重试一次先前未响应的代理,在 30 分钟之后进行第一次重试,在 1 小时之后进行第二次重试,依此类推。因此,如果您暂时关闭了代理服务器,客户机至多在其重新启动后 30 分钟便会重新开始使用该代理。

如果所有代理均出现故障,且未指定 DIRECT 返回值,浏览器将询问用户是否应暂时忽略代理而尝试直接进行连接浏览器将询问是否应在 20 分钟后重试代理,接着过 20 分钟会再次询问,依此类推,每次间隔时间为 20 分钟。

在以下示例中,返回值告知浏览器使用端口 8080 上名为 w3proxy.example.com 的代理。如果此代理不可用,则浏览器将使用端口 8080 上名为 proxy1.example.com 的代理:

PROXY w3proxy.example.com:8080; PROXY proxy1.example.com:8080

在下一个示例中,主代理为 w3proxy.example.com:8080。如果此代理不可用,则浏览器将使用 proxy1.example.com:8080。如果这两个代理都不可用,则浏览器将直接转至服务器。20 分钟之后,浏览器会询问用户是否应重试第一个代理。

PROXY w3proxy.example.com:8080; PROXY proxy1.example.com:8080; DIRECT

JavaScript 函数和环境

JavaScript 语言具有多个预定义的函数和环境条件,它们对于执行代理很有用。这些函数中的每一个均会检查是否满足某个特定条件,然后返回 true 或 false 值。相关的实用程序函数属于例外情况,因为它们返回 DNS 主机名或 IP 地址。您可以在主 FindProxyForURL() 函数中使用这些函数,以确定要发送给浏览器的返回值。有关这些函数的具体使用方法,请参见本章后面的示例。

本节将介绍各个函数或环境条件。适用于浏览器与代理集成的函数和环境条件如下:

基于主机名的函数

通过基于主机名的函数,可以使用主机名或 IP 地址来确定要使用的代理(如果有)。

dnsDomainIs()(host, domain)

dnsDomainIs()() 函数将检测 URL 主机名是否属于给定的 DNS 域。如果要将浏览器配置为不对本地域使用代理,则此函数很有用,如示例 1:代理除本地主机之外的所有服务器示例 2:代理防火墙外部的本地服务器中所示。

在某些情况下会基于 URL 所属的 DNS 域从一组代理中选择接收请求的代理,当您在这些情况下使用多个代理进行负载平衡时,此函数也很有用。例如,如果要通过将包含 .edu 的 URL 定向到一个代理,而将包含 .com 的 URL 定向到另一个代理来进行负载平衡,则可以使用 dnsDomainIs()() 来检查 URL 主机名。

参数

host 是 URL 中的主机名。

domain 是对主机名进行测试所用的域名。

返回值

true 或 false

示例

以下语句将为 true:

dnsDomainIs("www.example.com", ".example.com")

以下语句将为 false:

dnsDomainIs("www", ".example.com") dnsDomainIs("www.mcom.com", 
	".example.com")

isInNet()(host, pattern, mask)

使用 isInNet()() 函数,可以将 URL 主机名解析为 IP 地址,并测试它是否属于掩码所指定的子网。这与 SOCKS 所使用的 IP 地址模式匹配属于同一类型。请参见示例 4:直接连接到子网

参数:

host 是 DNS 主机名或 IP 地址。如果传递的是主机名,此函数会将其解析为 IP 地址。

pattern 是采用点分隔格式的 IP 地址模式。

mask 是 IP 地址模式掩码,用于确定应对 IP 地址的哪些部分进行匹配。值为 0 表示忽略;值为 255 表示匹配。如果主机的 IP 地址与指定的 IP 地址模式匹配,则此函数为 true。

返回值

true 或 false

示例

仅当主机的 IP 地址与 198.95.249.79 完全匹配时,此语句才为 true:

isInNet(host, "198.95.249.79", "255.255.255.255")

仅当主机的 IP 地址与 198.95.*.* 匹配时,此语句才为 true: isInNet(host, "198.95.0.0", "255.255.0.0")

isPlainhost name()(host)

isPlainhost name()() 函数将检测所请求 URL 中的主机名是普通主机名还是全限定域名。如果希望浏览器直接连接到本地服务器,则此函数会很有用,如示例 1:代理除本地主机之外的所有服务器示例 2:代理防火墙外部的本地服务器中所示。

参数

host 是 URL 中的主机名,仅当主机名中没有域名(无带点的段)时才不包括端口号。

返回值

如果 host 为本地的,则返回 true;如果 host 为远程的,则返回 false

示例

isPlainhost name("host")

如果 host 为形如 www 的字符串,此函数返回 true。如果 host 为形如 www.example.com 的字符串,此函数返回 false。

isResolvable()(host)

如果防火墙内的 DNS 仅识别内部主机,则可以使用 isResolvable()() 函数来测试主机名相对于网络是内部的还是外部的。使用此函数,可以将浏览器配置为对内部服务器使用直接连接,而仅对外部服务器使用代理。在一些站点,防火墙内的内部主机能够解析其他内部主机的 DNS 域名,但所有外部主机均不可解析,对于此类站点,此函数将很有用。isResolvable()() 函数通过查询 DNS 尝试将主机名解析为 IP 地址。请参见示例 3:仅代理未解析的主机

参数

host() 是 URL 中的主机名。

返回值

如果此函数可以解析主机名,则返回 true;如果不能解析,则返回 false

示例

isResolvable("host")

如果 host() 为形如 www 的字符串,并可通过 DNS 解析,则此函数返回 true。

localHostOrDomainIs()(host, hostdom)

localHostOrDomainIs()() 函数指定可以通过全限定域名或普通主机名访问的本地主机。请参见示例 2:代理防火墙外部的本地服务器

如果主机名与指定的主机名完全匹配,或者主机名中没有与非限定主机名匹配的域名部分,localHostOrDomainIs()() 函数将返回 true

参数

host 是 URL 中的主机名。

hostdom 是要匹配的全限定主机名。

返回值

true 或 false

示例

以下语句为 true(完全匹配):

localHostOrDomainIs("www.example.com", "www.example.com")

以下语句为 true(主机名匹配,未指定域名):

localHostOrDomainIs("www", "www.example.com")

以下语句为 false(域名不匹配):

localHostOrDomainIs("www.mcom.com", "www.example.com")

以下语句为 false(主机名不匹配):

localHostOrDomainIs("home.example.com", "www.example.com")

实用程序函数

通过实用程序函数,可以查明域级别、运行浏览器的主机或主机的 IP 地址。

dnsDomainLevels()(host)

dnsDomainLevels()() 函数查找 URL 主机名中的 DNS 级别数(圆点数)。

参数

host 是 URL 中的主机名。

返回值

DNS 域级别数(整数)。

示例

dnsDomainLevels("www") 将返回 0。

dnsDomainLevels("www.example.com") 将返回 2。

dnsResolve()(host)

dnsResolve()() 函数解析给定主机(通常来自 URL)的 IP 地址。如果 JavaScript 函数必须进行比现有函数所能完成的更高级的模式匹配,则此函数将很有用。

参数

host 是要解析的主机名。将给定的 DNS 主机名解析为 IP 地址,并以点分隔格式的字符串形式将其返回。

返回值

字符串值形式的点四分 IP 地址

示例

以下示例将返回字符串 198.95.249.79

dnsResolve("home.example.com")

myIpAddress()()

当 JavaScript 函数须根据运行浏览器的具体主机而采取不同行为时,myIpAddress()() 函数将很有用。此函数将返回运行浏览器的计算机的 IP 地址。

返回值

字符串值形式的点四分 IP 地址

示例:

如果要在计算机 home.example.com 上运行 Navigator,以下示例将返回字符串 198.95.249.79

myIpAddress()

基于 URL/主机名的条件

可通过匹配主机名或 URL 来进行负载平衡和路由选择。

shExpMatch()(str, shexp)

shExpMatch()() 函数将对 URL 主机名或 URL 本身进行匹配。此函数的主要用途是进行负载平衡并将 URL 以智能化方式路由到不同的代理服务器。

参数

str 是要比较的任何字符串(例如,URL 或主机名)。

shexp 是进行比较时所依据的 shell 表达式。

如果字符串与指定的 shell 表达式匹配,则此表达式为 true。请参见示例 6:使用 shExpMatch()() 平衡代理负载

返回值

true 或 false

示例

第一个示例将返回 true。第二个示例将返回 false。

shExpMatch("http://home.example.com/people/index.html",
            ".*/people/.*")
shExpMatch("http://home.example.com/people/yourpage/index.html",
            ".*/mypage/.*")

基于时间的条件

您可以使 FindProxyForURL 函数根据日期、时间或星期几而采取不同的行为。

dateRange() (day, month, year...)

dateRange()() 函数检测某个特定日期或日期范围,例如 1996 年 4 月 19 日到 1996 年 5 月 3 日。如果您希望 FindProxyForURL() 函数视当天日期而执行不同操作(例如,如果为其中一个代理服务器安排了定期停机维护时间),则此函数将很有用。

可采用多种方式指定日期范围:

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 是一个四位整数,代表年度(例如,1996)。

gmt 可以是字符串 "GMT",表示应采用格林尼治标准时间进行时间比较;也可以留空,从而假定时间采用本地时区。可在任何调用配置文件中指定 GMT 参数,不过,它始终都是作为最后一个参数。如果在每个类别 (day, month, year) 中仅指定一个值,则此函数仅在与指定值匹配的日子才会返回 true 值。如果指定了两个值,则从指定的第一个时间到指定的第二个时间,结果均为 true。

示例

以下语句在当地时区每月的第一天为 true:dateRange(1)

以下语句在格林尼治标准时间每月的第一天为 true:dateRange(1, "GMT")

以下语句对于每月的上半月为 true:dateRange(1, 15)

以下语句在每年的 12 月 24 日为 true:dateRange(24, "DEC")

以下语句在 1995 年 12 月 24 日为 true:dateRange(24, "DEC", 1995)

以下语句在一年的第一季度为 true:dateRange("JAN", "MAR")

以下语句从每年的 6 月 1 日到 8 月 15 日为 true:dateRange(1, "JUN", 15, "AUG")

以下语句从 1995 年 6 月 1 日直至 1995 年 8 月 15 日均为 true:dateRange(1, "JUN", 15, 1995, "AUG", 1995)

以下语句从 1995 年 10 月到 1996 年 3 月为 true:dateRange("OCT", 1995, "MAR", 1996)

以下语句在 1995 全年均为 true:dateRange(1995)

以下语句从 1995 年初直至 1997 年末均为 true:dateRange(1995, 1997)

timeRange (hour, minute, second...)

timeRange() 函数检测一天中的某个特定时间或时间范围,例如 9 p.m. 到 12 a.m.。如果您希望 FindProxyForURL() 函数视当时具体时间执行不同的操作,则此函数将很有用。

timeRange(hour)timeRange(hour1, hour2)timeRange(hour1, min1, hour2, min2)timeRange(hour1, min1, sec1, hour2, min2, sec2)

参数:

hour 为小时,范围从 0 到 23。(0 表示午夜,23 表示 11:00 p.m.)。

min 为分钟数,范围从 0 到 59。

sec 为秒数,范围从 0 到 59。

gmt 可以是字符串 GMT(表示 GMT 时区),也可以未指定(表示本地时区)。对于每一个参数配置文件均可以使用此参数,而且它始终是最后一个参数。

返回值

true 或 false

示例:

以下语句从正午到 1:00 p.m.为 true:timerange(12, 13)

以下语句从 GMT 时间正午到 12:59 p.m. 为 true:timerange(12, "GMT")

以下语句从 9:00 a.m. 到 5:00 p.m.为 true:timerange(9, 17)

以下语句在午夜到午夜过后 30 秒之间为 true:timerange(0, 0, 0, 0, 0, 30)

weekdayRange()(wd1, wd2, gmt)

weekdayRange() 函数检测某一特定周日或某一周日范围,例如星期一到星期五。如果您希望 FindProxyForURL 函数视具体星期几而执行不同的操作,则此函数将很有用。

参数

wd1wd2 为以下任意一个周日字符串:SUN MON TUE WED THU FRI SAT

gmt 可以是 GMT(表示格林尼治标准时间),也可以留空(表示本地时间)。

只有第一个参数 wd1 为强制性参数。wd2gmt 可以分别留空或同时留空。

如果只有一个参数,则此函数将在该参数所表示的周日返回 true 值。如果指定字符串 GMT 作为第二个参数,则采用 GMT 时间,否则,采用本地时区的时间。

如果 wd1wd2 均被定义,则该条件在当前周日介于这两个周日之间时为 true。首末日期包括在内。参数顺序很重要;"MON," "WED" 指星期一到星期三,而 "WED," "MON" 是从星期三到下周的星期一。

示例

以下语句从星期一到星期五(本地时区)为 true。weekdayRange("MON", "FRI")

以下语句从格林尼治标准时间星期一到星期五为 true。weekdayRange("MON", "FRI", "GMT")

以下语句在本地时间星期六为 true。weekdayRange("SAT")

以下语句在格林尼治标准时间星期六为 true。weekdayRange("SAT", "GMT")

以下语句从星期五到下星期一为 true(顺序很重要)。weekdayRange("FRI", "MON")

函数示例

本节提供详细的 JavaScript 函数示例。

示例 1:代理除本地主机之外的所有服务器

在本例中,浏览器直接连接到非全限定的所有主机以及本地域中的主机。所有其他主机均要经过名为 w3proxy.example.com:8080 的代理。


注 –

如果此代理出现故障,则自动进行直接连接。


    function FindProxyForURL(url, host)
    {
        if (isPlainhost name(host) ||
            dnsDomainIs(host, ".example.com") ||
            dnsDomainIs(host, ".mcom.com"))
            return "DIRECT";
        else
            return "PROXY w3proxy.example.com:8080; DIRECT";
    }

示例 2:代理防火墙外部的本地服务器

本例类似于示例 1:代理除本地主机之外的所有服务器,只是它将对防火墙外部的本地服务器使用代理。如果存在属于本地域而位于防火墙之外的主机(如主 Web 服务器),并且只有通过代理服务器才能访问到这些主机,则使用 localHostOrDomainIs()() 函数来处理这些例外情况:

    function FindProxyForURL(url, host)
    {
        if ((isPlainhost name(host) ||
        dnsDomainIs(host, ".example.com")) &&
        !localHostOrDomainIs(host, "www.example.com") &&
        !localHostOrDoaminIs(host, "merchant.example.com"))
            return "DIRECT";
        else
            return "PROXY w3proxy.example.com:8080; DIRECT";
    }

本例对 example.com 域中除本地主机之外的所有主机使用代理。主机 www.example.commerchant.example.com 也要经过代理。

指定适当的例外情况顺序可以提高效率:localHostOrDomainIs()() 函数仅对本地域中的 URL 才会执行,而不是对于每个 URL 都要执行。请特别留意 and 表达式之前的 or 表达式两边的括号。

示例 3:仅代理未解析的主机

本例适用于内部 DNS 仅解析内部主机名的环境,其目的是仅对无法解析的主机使用代理。

    function FindProxyForURL(url, host)
    {
        if (isResolvable(host))
                return "DIRECT";
            else
                return "PROXY proxy.mydomain.com:8080";
    }

本例要求每次都查询 DNS。因此,可将本例与其他规则组合在一起使用,以便仅在其他规则无法生成结果时查询 DNS。

    function FindProxyForURL(url, host)
    {
        if (isPlainhost name(host) ||
            dnsDomainIs(host, ".mydomain.com") ||
            isResolvable(host))
            return "DIRECT";
        else
            return "PROXY proxy.mydomain.com:8080";
    }

示例 4:直接连接到子网

在本例中,给定子网中的所有主机将直接进行连接,而其他主机则要经过代理。

    function FindProxyForURL(url, host)
    {
        if (isInNet(host, "198.95.0.0", "255.255.0.0"))
            return "DIRECT";
        else
            return "PROXY proxy.mydomain.com:8080";
    }

在本例中,可以通过在开头添加冗余规则来最大程度地减少对 DNS 的使用:

    function FindProxyForURL(url, host)
    {
        if (isPlainhost name(host) ||
            dnsDomainIs(host, ".mydomain.com") ||
            isInNet(host, "198.95.0.0", "255.255.0.0"))
            return "DIRECT";
        else
            return "PROXY proxy.mydomain.com:8080";
    }

示例 5:使用 dnsDomainIs()() 平衡代理负载

本例较为复杂。它使用四个代理服务器,其中一个充当其他服务器的热备份。如果其余三个代理服务器中的任何一个出现故障,则第四个服务器将进行接管。其余三个代理服务器基于 URL 模式分担负载,从而使它们的高速缓存变得更加有效。任何文档在这三个服务器上都只有一个副本,而不是在其中每一个服务器上均有一个副本。分配负载如下表所示。

表 17–3 平衡代理负载

代理 

用途 

#1 

.com

#2 

.edu

#3 

其他所有域 

#4 

热备份 

所有本地访问均应为直接访问。所有代理服务器都在端口 8080 上运行。您可以使用 + 运算符来串联字符串。

function FindProxyForURL(url, host)
{
    if (isPlainhost name(host) || dnsDomainIs(host, ".mydomain.com"))
        return "DIRECT";

    else if (dnsDomainIs(host, ".com"))
        return "PROXY proxy1.mydomain.com:8080; " +
              "PROXY proxy4.mydomain.com:8080";

    else if (dnsDomainIs(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";
}

示例 6:使用 shExpMatch()() 平衡代理负载

本例与示例 5:使用 dnsDomainIs()() 平衡代理负载基本相同,但本例使用的是 shExpMatch()(),而不是 dnsDomainIs()()

    function FindProxyForURL(url, host)
    {
    if (isPlainhost name(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";
    }

示例 7:代理特定协议

可以设置代理,使其用于特定的协议。在 FindProxyForURL()() 函数中,可以使用大多数标准 JavaScript 功能。例如,要根据协议设置不同的代理,可以使用 substring()() 函数。

    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()() 函数也可以实现此配置;例如:

    ...
    if (shExpMatch(url, "http:*")) {
        return "PROXY http-proxy.mydomain.com:8080;
    }
    ...