查看源代码 httpd 行为 (inets v9.3.1)
HTTP 服务器 API
一个符合 RFC 2616 定义的 HTTP 1.1 兼容 Web 服务器的实现。提供 Web 服务器启动选项、管理功能和一个 Erlang 回调 API。
数据类型
在此模块中多次使用的类型定义
boolean() = true | false
string/0
= ASCII 字符列表
path() = string()
表示文件或目录路径
ip_address() = {N1,N2,N3,N4} % IPv4 | {K1,K2,K3,K4,K5,K6,K7,K8} % IPv6
hostname() = string()
表示主机,例如,“foo.bar.com”
property() = atom()
HTTP 服务器服务启动 & 停止
可以配置 Web 服务器在启动 Inets
应用程序时启动,也可以通过调用 Inets
应用程序 API inets:start(httpd, ServiceConfig)
或 inets:start(httpd, ServiceConfig, How)
在运行时动态启动,请参阅 inets
。配置选项(也称为属性)如下:
文件属性
当 Web 服务器在应用程序启动时启动时,属性将从配置文件中获取,该配置文件可以包含常规的 Erlang 属性列表,即 [{Option, Value}]
,其中 Option = property()
且 Value = term()
,后跟一个句点。如果 Web 服务器在运行时动态启动,则仍然可以指定文件,也可以指定完整的属性列表。
注意
注意:在 OTP-23 中,已删除对具有 Apache 语法的旧版配置文件的支持。
强制属性
{port, integer()}
HTTP 服务器监听的端口。如果将端口指定为零,则会选择一个任意的可用端口,并且可以使用函数httpd:info/2
来确定选择了哪个端口。{server_root, path()}
定义服务器的主目录,其中可以存储日志文件等。在其他属性中指定的相对路径是指此目录。
通信属性
{server_name, string()}
服务器的名称,通常是完全限定域名。如果未给出,则默认为
net_adm:localhost()
。{profile, atom()}
与bind_address
和port
一起使用,以唯一标识 HTTP 服务器。这在虚拟化环境中很有用,在虚拟化环境中,可能存在多个具有相同 bind_address 和端口的服务器。如果未显式设置此属性,则假定bind_address
和port
唯一标识了 HTTP 服务器。{socket_type, ip_comm | {ip_comm, Config::proplist()} | {ssl, Config::proplist()}}
有关ip_comm
配置选项,请参阅gen_tcp:listen/2
,某些 httpd 内部使用的选项无法设置。有关
SSL
配置选项,请参阅ssl:listen/2
。默认值为
ip_comm
。注意
OTP-25 弃用了通信属性
{socket_type, ip_comm | {ip_comm, Config::proplist()} | {essl, Config::proplist()}}
,并将其替换为{socket_type, ip_comm | {ip_comm, Config::proplist()} | {ssl, Config::proplist()}}
。{ipfamily, inet | inet6}
默认值为inet
,旧版选项inet6fb4
不再有意义,将被转换为 inet。{minimum_bytes_per_second, integer()}
如果给定,则为连接设置每秒字节数的最小值。如果未达到该值,则该连接的套接字将关闭。
该选项适用于降低“慢速 DoS”攻击的风险。
Erlang Web 服务器 API 模块
-
{modules, [atom()]}
定义 HTTP 服务器在处理请求时使用的模块。默认值为[mod_alias, mod_auth, mod_esi, mod_actions, mod_cgi, mod_dir, mod_get, mod_head, mod_log, mod_disk_log]
。请注意,某些mod
模块依赖于其他模块,因此顺序不能完全任意。有关详细信息,请参阅用户指南中的 Inets Web 服务器模块。
限制属性
{customize, atom()}
用于自定义 inets HTTP 服务器行为的回调模块,请参阅httpd_custom_api
{disable_chunked_transfer_encoding_send, boolean()}
允许您在向 HTTP/1.1 客户端发送响应时禁用分块传输编码。默认值为false
。{keep_alive, boolean()}
指示服务器在客户端声明符合 HTTP/1.1 标准时是否使用持久连接。默认值为true
。{keep_alive_timeout, integer()}
服务器在关闭连接之前等待客户端后续请求的秒数。默认值为150
。{max_content_length, integer()}
传入请求中的最大 content-length,以字节为单位。内容大于此值的请求将以状态 413 响应。默认值为100000000
(100 MB)。{max_keep_alive_request, integer()}
客户端可以在一个连接上执行的请求数。当服务器响应了由max_keep_alive_requests
定义的请求数时,服务器将关闭连接。即使有排队的请求,服务器也会关闭连接。默认值是没有限制。{max_client_body_chunk, integer()}
强制将 HTTP PUT 或 POST 主体数据分块,以传递到 mod_esi 回调。请注意,mod_cgi 不支持此功能。默认值是没有限制,即,整个主体将作为一个实体传递,这可能会非常消耗内存。mod_esi
。
管理属性
{mime_types, [{MimeType, Extension}] | path()}
MimeType = string()
且Extension = string()
。传递给客户端的文件根据 RFC 1590 进行 MIME 类型化。文件后缀在文件传递之前映射到 MIME 类型。文件后缀和 MIME 类型之间的映射可以在属性列表中指定。MIME 类型也可以从文件中读取。该文件应包含以下形式的行
MediaType [Extensions...]
,例如text/html html htm
。要配置此项,请指定其路径,例如{mime_types, "/etc/mime.types"}
。如果未设置,则如果存在,将使用
server_root
下的conf/mime.types
,否则,默认值为[{"html","text/html"},{"htm","text/html"}]
。{mime_type, string()}
当要求服务器提供无法通过 MIME 类型设置确定的文档类型时,服务器将使用此默认类型。{server_admin, string()}
定义服务器管理员的电子邮件地址,该地址将包含在服务器返回的任何错误消息中。{server_tokens, none|prod|major|minor|minimal|os|full|{private, string()}}
定义服务器标头值的样式。示例:假设
Inets
的版本为 5.8.1,则服务器标头字符串对于不同的服务器令牌值可以如下所示:none
- "" % 不会生成 Server: 标头prod
- "inets"major
- "inets/5"minor
- "inets/5.8"minimal
- "inets/5.8.1"os
- "inets/5.8.1 (unix)"full
- "inets/5.8.1 (unix/linux) OTP/R15B"{private, "foo/bar"}
- "foo/bar"
默认情况下,该值与之前相同,即
minimal
。{logger, Options::list()}
目前仅支持一个选项{error, ServerID::atom()}
- 在分层记录器 域下,在记录器 级别 error 上生成 记录器事件:[otp, inets, httpd, ServerID, error]
内置的记录器格式化函数从错误报告生成日志条目#{server_name => string() protocol => internal | 'TCP' | 'TLS' | 'HTTP', transport => "TCP" | "TLS", %% Present when protocol = 'HTTP' uri => string(), %% Present when protocol = 'HTTP' and URI is valid peer => inet:peername(), host => inet:hostname(), reason => term() }
一个仅使用 logger 默认设置的日志条目示例
=ERROR REPORT==== 9-Oct-2019::09:33:27.350235 === Server: My Server Protocol: HTTP Transport: TLS URI: /not_there Host: 127.0.1.1:80 Peer: 127.0.0.1:45253 Reason: [{statuscode,404},{description,"Object Not Found"}]
使用此选项会使 mod_log 和 mod_disk_log 的错误日志变得冗余。
添加过滤器
{fun logger_filters:domain/2, {log,equal,[otp,inets, httpd, ServerID, error]}
到适当的 logger 处理程序来处理事件。例如,要将 httpd 服务器中
ServerID
为my_server
的错误日志写入文件,可以使用以下 sys.config[{kernel, [{logger, [{handler, http_error_test, logger_std_h, #{config => #{ file => "log/http_error.log" }, filters => [{inets_httpd, {fun logger_filters:domain/2, {log, equal, [otp, inets, httpd, my_server, error] }}}], filter_default => stop }}]}]}].
或者,如果要通过 API 将其添加到默认 logger
logger:add_handler_filter(default, inets_httpd, {fun logger_filters:domain/2, {log, equal, [otp, inets, httpd, my_server, error]}}).
{log_format, common | combined}
定义访问日志是否按照common
日志格式或扩展的 common 日志格式写入。common
格式是一行,如下所示:remotehost rfc931 authuser [date] "request" status bytes
。这里
remotehost
- 远程主机。rfc931
- 客户端的远程用户名 (RFC 931)。authuser
- 用于身份验证的用户名。[date]
- 请求的日期和时间 (RFC 1123)。"request"
- 来自客户端的请求行 (RFC 1945)。status
- 返回给客户端的 HTTP 状态码 (RFC 1945)。bytes
- 传输的文档的内容长度。
combined
格式是一行,如下所示:remotehost rfc931 authuser [date] "request" status bytes "referer" "user_agent"
除了之前的
"referer"
- 客户端在请求 URL 之前所在的 URL(如果无法确定,则此字段中会放置一个减号)。"user_agent"
- 客户端声称正在使用的软件(如果无法确定,则此字段中会放置一个减号)。
这会影响
mod_log
和mod_disk_log
写入的访问日志。{error_log_format, pretty | compact}
默认值为pretty
。如果错误日志是要由人直接读取的,pretty
是最佳选择。pretty
的格式对应于io:format("[~s] ~s, reason: ~n ~p ~n~n", [Date, Msg, Reason]).
compact
的格式对应于io:format("[~s] ~s, reason: ~w ~n", [Date, Msg, Reason]).
这会影响
mod_log
和mod_disk_log
写入的错误日志。
URL 别名属性 - 需要 mod_alias
{alias, {Alias, RealName}}
Alias = string()
和RealName = string()
。alias
允许将文档存储在本地文件系统中,而不是document_root
位置。路径以 url-path 开头的 URL 将映射到以 directory-filename 开头的本地文件,例如{alias, {"/image", "/ftp/pub/image"}}
访问 http://your.server.org/image/foo.gif 将引用文件 /ftp/pub/image/foo.gif。
{re_write, {Re, Replacement}}
Re = string()
和Replacement = string()
。re_write
允许将文档存储在本地文件系统中,而不是document_root
位置。URL 通过re:replace/3
重写,以在本地文件系统中生成路径,例如{re_write, {"^/[~]([^/]+)(.*)$", "/home/\\1/public\\2"}}
访问 http://your.server.org/~bob/foo.gif 将引用文件 /home/bob/public/foo.gif。
{directory_index, [string()]}
directory_index
指定一个资源列表,如果客户端请求一个以/
结尾的目录,则会查找这些资源。file
描述目录中文件的名称。可以提供多个文件,在这种情况下,服务器返回找到的第一个文件,例如{directory_index, ["index.html", "welcome.html"]}
访问 http://your.server.org/docs/ 将返回 http://your.server.org/docs/index.html 或 http://your.server.org/docs/welcome.html (如果 index.html 不存在)。
CGI 属性 - 需要 mod_cgi
{script_alias, {Alias, RealName}}
Alias = string()
和RealName = string()
。与属性alias
具有相同的行为,只是它们还将目标目录标记为包含 CGI 脚本。路径以 url-path 开头的 URL 将映射到以 directory-filename 开头的脚本,例如{script_alias, {"/cgi-bin/", "/web/cgi-bin/"}}
访问 http://your.server.org/cgi-bin/foo 将导致服务器运行脚本 /web/cgi-bin/foo。
{script_re_write, {Re, Replacement}}
Re = string()
和Replacement = string()
。与属性re_write
具有相同的行为,只是它们还将目标目录标记为包含 CGI 脚本。路径以 url-path 开头的 URL 将映射到以 directory-filename 开头的脚本,例如{script_re_write, {"^/cgi-bin/(\\d+)/", "/web/\\1/cgi-bin/"}}
访问 http://your.server.org/cgi-bin/17/foo 将导致服务器运行脚本 /web/17/cgi-bin/foo。
{script_nocache, boolean()}
如果script_nocache
设置为true
,HTTP 服务器默认会添加必要的标头字段,以防止代理缓存页面。通常,这是首选的。默认为false
。{script_timeout, integer()}
Web 服务器在等待脚本的每块数据之间等待的时间(以秒为单位)。如果 CGI 脚本在超时之前没有传递任何数据,则与客户端的连接将关闭。默认值为15
。{action, {MimeType, CgiScript}}
- 需要mod_actions
MimeType = string()
和CgiScript = string()
。当请求特定 MIME 类型的文件时,action
添加一个激活 CGI 脚本的操作。它使用标准的 CGI PATH_INFO 和 PATH_TRANSLATED 环境变量来传播所请求文档的 URL 和文件路径。示例
{action, {"text/plain", "/cgi-bin/log_and_deliver_text"}}
{script, {Method, CgiScript}}
- 需要mod_actions
Method = string()
和CgiScript = string()
。当使用特定的 HTTP 方法请求文件时,script
添加一个激活 CGI 脚本的操作。该方法可以是 GET 或 POST,如 RFC 1945 中定义的那样。它使用标准的 CGI PATH_INFO 和 PATH_TRANSLATED 环境变量来传播所请求文档的 URL 和文件路径。示例
{script, {"PUT", "/cgi-bin/put"}}
ESI 属性 - 需要 mod_esi
{erl_script_alias, {URLPath, [AllowedModule]}}
URLPath = string()
和AllowedModule = atom()
。erl_script_alias
将所有与 url-path 匹配的 URL 标记为 erl 方案脚本。匹配的 URL 将映射到特定的模块和函数,例如{erl_script_alias, {"/cgi-bin/example", [httpd_example]}}
对 http://your.server.org/cgi-bin/example/httpd_example:yahoo 的请求将引用 httpd_example:yahoo/3,或者如果该函数不存在,则引用 httpd_example:yahoo/2,并且不允许执行 http://your.server.org/cgi-bin/example/other:yahoo。
{erl_script_nocache, boolean()}
如果erl_script_nocache
设置为true
,服务器会添加 HTTP 标头字段,以防止代理缓存页面。对于动态内容,这通常是一个好主意,因为内容通常在每次请求之间都会有所不同。默认值为false
。{erl_script_timeout, integer()}
如果erl_script_timeout
设置服务器在通过mod_esi:deliver/2
传递的每块数据之间等待的时间(以秒为单位)。默认值为15
。这仅与使用 erl 方案的脚本相关。
日志属性 - 需要 mod_log
{error_log, path()}
定义用于记录服务器错误的错误日志文件的文件名。如果文件名不以斜杠 (/) 开头,则假定它相对于server_root
。{security_log, path()}
定义用于记录安全事件的访问日志文件的文件名。如果文件名不以斜杠 (/) 开头,则假定它相对于server_root
。{transfer_log, path()}
定义用于记录传入请求的访问日志文件的文件名。如果文件名不以斜杠 (/) 开头,则假定它相对于server_root
。
磁盘日志属性 - 需要 mod_disk_log
{disk_log_format, internal | external}
定义日志文件的文件格式。有关详细信息,请参阅disk_log
。如果使用内部文件格式,则崩溃后会修复日志文件。修复日志文件时,数据可能会丢失。如果使用外部文件格式,则如果日志文件损坏,httpd
不会启动。默认值为external
。{error_disk_log, path()}
定义用于记录服务器错误的 (disk_log
) 错误日志文件的文件名。如果文件名不以斜杠 (/) 开头,则假定它相对于server_root
。{error_disk_log_size, {MaxBytes, MaxFiles}}
MaxBytes = integer()
和MaxFiles = integer()
。定义 (disk_log
) 错误日志文件的属性。此文件类型为环绕日志,最大字节数写入每个文件,并且在截断和重用第一个文件之前使用最大文件数。{security_disk_log, path()}
定义用于记录传入的安全事件(即,经过身份验证的请求)的 (disk_log
) 访问日志文件的文件名。如果文件名不以斜杠 (/) 开头,则假定它相对于server_root
。{security_disk_log_size, {MaxBytes, MaxFiles}}
MaxBytes = integer()
和MaxFiles = integer()
。定义disk_log
访问日志文件的属性。此文件类型为环绕日志,最大字节数写入每个文件,并且在截断和重用第一个文件之前使用最大文件数。{transfer_disk_log, path()}
定义用于记录传入请求的(disk_log
)访问日志文件的文件名。如果文件名不是以斜杠 (/) 开头,则假定该文件路径是相对于server_root
的。{transfer_disk_log_size, {MaxBytes, MaxFiles}}
MaxBytes = integer()
和MaxFiles = integer()
。定义disk_log
访问日志文件的属性。此文件类型为环绕日志,最大字节数写入每个文件,并且在截断和重用第一个文件之前使用最大文件数。
身份验证属性 - 需要 mod_auth
{directory, {path(), [{property(), term()}]}}
目录的属性如下:
{allow_from, all | [RegxpHostString]}
定义一组允许访问给定目录的主机,例如:{allow_from, ["123.34.56.11", "150.100.23"]}
主机
123.34.56.11
和150.100.23
子网上的所有机器都允许访问。{deny_from, all | [RegxpHostString]}
定义一组拒绝访问给定目录的主机,例如:{deny_from, ["123.34.56.11", "150.100.23"]}
主机
123.34.56.11
和150.100.23
子网上的所有机器都不允许访问。{auth_type, plain | dets | mnesia}
设置用于目录的身份验证数据库类型。不同方法之间的主要区别在于,当使用 Mnesia 和 Dets 时,可以保存动态数据。{auth_user_file, path()}
设置包含用户和密码列表以进行用户身份验证的文件名。文件名可以是绝对路径或相对于server_root
的相对路径。如果使用 plain 存储方法,此文件是一个纯文本文件,其中每行包含一个用户名,后跟一个冒号,然后是未加密的密码。如果用户名重复,则行为未定义。示例
ragnar:s7Xxv7 edward:wwjau8
如果使用 Dets 存储方法,则用户数据库由 Dets 维护,不得手动编辑。使用模块
mod_auth
中的 API 函数创建/编辑用户数据库。如果使用 Mnesia 存储方法,则忽略此指令。出于安全原因,请确保auth_user_file
存储在 Web 服务器的文档树之外。如果将其放置在它保护的目录中,则客户端可以下载它。{auth_group_file, path()}
设置包含用户组列表以进行用户身份验证的文件名。文件名可以是绝对路径或相对于server_root
的相对路径。如果使用 plain 存储方法,则组文件是一个纯文本文件,其中每行包含一个组名称,后跟一个冒号,然后是以空格分隔的成员用户名。示例
group1: bob joe ante
如果使用 Dets 存储方法,则组数据库由 Dets 维护,不得手动编辑。使用模块
mod_auth
的 API 创建/编辑组数据库。如果使用 Mnesia 存储方法,则忽略此指令。出于安全原因,请确保auth_group_file
存储在 Web 服务器的文档树之外。如果将其放置在它保护的目录中,则客户端可以下载它。{auth_name, string()}
设置目录的授权领域(auth-domain)的名称。此字符串告知客户端要使用的用户名和密码。{auth_access_password, string()}
如果设置为除"NoPassword"
以外的其他值,则所有 API 调用都需要密码。如果密码设置为"DummyPassword"
,则必须在任何其他 API 调用之前更改密码。为了保护身份验证数据,必须在 Web 服务器启动后更改密码。否则,它将以明文形式写入配置文件。
安全属性 - 需要 mod_security
{security_directory, {path(), [{property(), term()}]}}
安全目录的属性如下:
{data_file, path()}
安全数据文件的名称。文件名可以是绝对路径或相对于server_root
的相对路径。此文件用于存储模块mod_security
的持久数据。{max_retries, integer()}
指定在用户被阻止之前尝试验证用户的最大次数。如果用户在被阻止时成功验证身份,则服务器会向用户返回 403(禁止)响应。如果用户在被阻止时尝试失败,出于安全原因,服务器将返回 401(未授权)。默认值为3
。可以设置为无限。{block_time, integer()}
指定用户被阻止的分钟数。此时间过后,用户将自动重新获得访问权限。默认值为60
。{fail_expire_time, integer()}
指定记住用户身份验证失败的分钟数。如果用户在此时间过后进行身份验证,则会忘记以前的身份验证失败。默认值为30
。{auth_timeout, integer()}
指定记住成功用户身份验证的秒数。此时间过后,身份验证不再报告。默认值为30
。
Web 服务器 API 数据类型
Erlang Web 服务器 API 数据类型如下:
ModData = #mod{}
-record(mod, {
data = [],
socket_type = ip_comm,
socket,
config_db,
method,
absolute_uri,
request_uri,
http_version,
request_line,
parsed_header = [],
entity_body,
connection
}).
要在您的回调模块中访问记录,请使用:
-include_lib("inets/include/httpd.hrl").
记录 mod
的字段具有以下含义:
data
- 类型[{InteractionKey,InteractionValue}]
用于在模块之间传播数据。在函数类型声明中描述为interaction_data()
。socket_type
-socket_type()
指示它是 IP 套接字还是ssl
套接字。socket
- 套接字,格式为ip_comm
或ssl
,具体取决于socket_type
。config_db
- 配置文件指令作为键值元组存储在 ETS 表中。在函数类型声明中描述为config_db()
。method
- 类型为"GET" | "POST" | "HEAD" | "TRACE"
,即 HTTP 方法。absolute_uri
- 如果请求是 HTTP/1.1 请求,则 URI 可以采用绝对 URI 格式。在这种情况下,httpd
会将绝对 URI 保存在此字段中。绝对 URI 的示例为"http://ServerName:Part/cgi-bin/find.pl?person=jocke"
request_uri
- RFC 1945 中定义的Request-URI
,例如,"/cgi-bin/find.pl?person=jocke"
。http_version
- 请求的HTTP
版本,即 "HTTP/1.0" 或 "HTTP/1.1"。request_line
- RFC 1945 中定义的Request-Line
,例如,"GET /cgi-bin/find.pl?person=jocke HTTP/1.0"
。parsed_header
- 类型[{HeaderKey,HeaderValue}]
。parsed_header
包含 HTTP 请求中的所有 HTTP 标头字段,这些字段以键值元组列表形式存储。有关所有标头字段的列表,请参阅 RFC 2616。例如,日期字段存储为{"date","Wed, 15 Oct 1997 14:35:17 GMT"}
。RFC 2616 定义 HTTP 是一种不区分大小写的协议,并且标头字段可以是小写或大写。httpd
确保所有标头字段名称均为小写。entity_body
- RFC 2616 中定义的entity-Body
,例如,使用 POST 方法从 CGI 脚本发送的数据。connection
-true | false
。如果设置为true
,则与客户端的连接是一个持久连接,并且在请求得到服务时不会关闭。
另请参阅
总结
回调
当有效请求到达 httpd
时,它会在每个模块中调用 do/1
,该模块由 Module
的配置选项定义。该函数可以为其他模块生成数据,或生成可以发送回客户端的响应。
当 httpd
关闭时,它会尝试在每个 Erlang Web 服务器回调模块中执行 remove/1
。程序员可以使用此函数来清理在 store 函数中创建的资源。
在将配置选项保存到内部数据库之前,检查配置选项的有效性。此函数还可以具有副作用,即设置配置选项所隐含的必要额外资源。它还可以通过更改选项的值来解决配置选项之间可能的依赖关系。此函数仅需要为此特定回调模块实现的选项设置子句。
Web 服务器 API 帮助函数
parse_query/1
将传入的数据解析为 erl
和 eval
脚本(请参阅 mod_esi
),格式遵循标准的 URL 格式,即 '+' 变成 '空格',并解码十六进制字符 (%xx
)。
函数
获取有关 HTTP 服务器的信息。当仅使用 pid 调用时,将获取所有属性。当使用特定属性列表调用时,将获取这些属性。可用属性与服务器的启动选项相同。
获取有关 HTTP 服务器的信息。当仅使用 Address
和 Port
调用时,将获取所有属性。当使用特定属性列表调用时,将获取这些属性。可用属性与服务器的启动选项相同。
重新加载 HTTP 服务器配置,而无需重启服务器。在重新加载期间,传入的请求会以临时关闭消息响应。
类型
回调
-callback do(ModData) -> {proceed, OldData} | {proceed, NewData} | {break, NewData} | done when ModData :: [{data, NewData} | {'Body', Body} | {'Head', Head}], OldData :: list(), NewData :: [{response, {StatusCode, Body}}], StatusCode :: integer(), Body :: iolist() | nobody | {Fun, FunArg}, Head :: [HeaderOption], HeaderOption :: {Option, Value} | {code, StatusCode}, Option :: accept_ranges | allow, Value :: string(), FunArg :: [term()], Fun :: fun((FunArg) -> sent | close | Body).
当有效请求到达 httpd
时,它会在每个模块中调用 do/1
,该模块由 Module
的配置选项定义。该函数可以为其他模块生成数据,或生成可以发送回客户端的响应。
ModData
中的字段 data
是一个列表。此列表是上次调用 do/1
返回的列表。
Body
是发送回客户端的 HTTP 响应正文。相应的标头会附加到消息中。StatusCode
是响应的状态码,有关适当的值,请参阅 RFC 2616。
Head
是 HTTP 标头字段的键值列表。服务器从此数据构造 HTTP 标头。有关每个标头字段的适当值,请参阅 RFC 2616。如果客户端是 HTTP/1.0 客户端,服务器将过滤列表,以便只将 HTTP/1.0 标头字段发送回客户端。
如果返回的 Body
等于 {Fun,Arg}
,则 Web 服务器会尝试对 Fun
使用 apply/2
,并将 Arg
作为参数。Web 服务器期望该函数要么返回 HTTP 响应列表 (Body)
,要么返回原子 sent
(如果 HTTP 响应已发送回客户端)。如果函数返回 close
,则表示出现问题,服务器将通过关闭连接向客户端发出信号。
当 httpd
关闭时,它会尝试在每个 Erlang Web 服务器回调模块中执行 remove/1
。程序员可以使用此函数来清理在 store 函数中创建的资源。
-callback store({Option, Value}, Config) -> {ok, {Option, NewValue}} | {error, Reason} when Option :: property(), Config :: [{Option, Value}], Value :: term(), NewValue :: term(), Reason :: term().
在将配置选项保存到内部数据库之前,检查配置选项的有效性。此函数还可以具有副作用,即设置配置选项所隐含的必要额外资源。它还可以通过更改选项的值来解决配置选项之间可能的依赖关系。此函数仅需要为此特定回调模块实现的选项设置子句。
Web 服务器 API 辅助函数
-spec parse_query(QueryString) -> QueryList | uri_string:error() when QueryString :: string(), QueryList :: [{unicode:chardata(), unicode:chardata() | true}].
parse_query/1
将传入的数据解析为 erl
和 eval
脚本(请参阅 mod_esi
),格式遵循标准的 URL 格式,即 '+' 变成 '空格',并解码十六进制字符 (%xx
)。
函数
-spec info(Pid) -> HttpInformation when Pid :: pid(), Path :: file:name_all(), HttpInformation :: [CommonOption] | [CommunicationOption] | [ModOption] | [LimitOption] | [AdminOption], CommonOption :: {port, non_neg_integer()} | {server_name, string()} | {server_root, Path} | {document_root, Path}, CommunicationOption :: {bind_address, inet:ip_address() | inet:hostname() | any} | {profile, atom()} | {socket_type, ip_comm | {ip_comm, ssl:tls_option() | gen_tcp:option()} | {ssl, ssl:tls_option() | gen_tcp:option()}} | {ipfamily, inet | inet6} | {minimum_bytes_per_second, integer()}, ModOption :: {modules, atom()}, LimitOption :: {customize, atom()} | {disable_chunked_transfer_encoding_send, boolean()} | {keep_alive, boolean()} | {keep_alive_timeout, integer()} | {max_body_size, integer()} | {max_clients, integer()} | {max_header_size, integer()} | {max_content_length, integer()} | {max_uri_size, integer()} | {max_keep_alive_request, integer()} | {max_client_body_chunk, integer()}, AdminOption :: {mime_types, [{MimeType :: string(), Extension :: string()}] | Path} | {mime_type, string()} | {server_admin, string()} | {server_tokens, none | prod | major | minor | minimal | os | full | {private, string()}} | {logger, Options :: list()} | {log_format, common | combined} | {error_log_format, pretty | compact}.
等效于 info/2
。
-spec info(Pid, Properties) -> HttpInformation when Pid :: pid(), Properties :: [atom()], HttpInformation :: [CommonOption] | [CommunicationOption] | [ModOption] | [LimitOption] | [AdminOption], CommonOption :: {port, non_neg_integer()} | {server_name, string()} | {server_root, Path} | {document_root, Path}, CommunicationOption :: {bind_address, inet:ip_address() | inet:hostname() | any} | {profile, atom()} | {socket_type, ip_comm | {ip_comm, ssl:tls_option() | gen_tcp:option()} | {ssl, ssl:tls_option() | gen_tcp:option()}} | {ipfamily, inet | inet6} | {minimum_bytes_per_second, integer()}, ModOption :: {modules, atom()}, LimitOption :: {customize, atom()} | {disable_chunked_transfer_encoding_send, boolean()} | {keep_alive, boolean()} | {keep_alive_timeout, integer()} | {max_body_size, integer()} | {max_clients, integer()} | {max_header_size, integer()} | {max_content_length, integer()} | {max_uri_size, integer()} | {max_keep_alive_request, integer()} | {max_client_body_chunk, integer()}, AdminOption :: {mime_types, [{MimeType :: string(), Extension :: string()}] | Path} | {mime_type, string()} | {server_admin, string()} | {server_tokens, none | prod | major | minor | minimal | os | full | {private, string()}} | {logger, Options :: list()} | {log_format, common | combined} | {error_log_format, pretty | compact}; (Address, Port) -> HttpInformation when Address :: inet:ip_address(), Port :: integer(), Path :: file:name_all(), HttpInformation :: [CommonOption] | [CommunicationOption] | [ModOption] | [LimitOption] | [AdminOption], CommonOption :: {port, non_neg_integer()} | {server_name, string()} | {server_root, Path} | {document_root, Path}, CommunicationOption :: {bind_address, inet:ip_address() | inet:hostname() | any} | {profile, atom()} | {socket_type, ip_comm | {ip_comm, ssl:tls_option() | gen_tcp:option()} | {ssl, ssl:tls_option() | gen_tcp:option()}} | {ipfamily, inet | inet6} | {minimum_bytes_per_second, integer()}, ModOption :: {modules, atom()}, LimitOption :: {customize, atom()} | {disable_chunked_transfer_encoding_send, boolean()} | {keep_alive, boolean()} | {keep_alive_timeout, integer()} | {max_body_size, integer()} | {max_clients, integer()} | {max_header_size, integer()} | {max_content_length, integer()} | {max_uri_size, integer()} | {max_keep_alive_request, integer()} | {max_client_body_chunk, integer()}, AdminOption :: {mime_types, [{MimeType :: string(), Extension :: string()}] | Path} | {mime_type, string()} | {server_admin, string()} | {server_tokens, none | prod | major | minor | minimal | os | full | {private, string()}} | {logger, Options :: list()} | {log_format, common | combined} | {error_log_format, pretty | compact}.
获取有关 HTTP 服务器的信息。当仅使用 pid 调用时,将获取所有属性。当使用特定属性列表调用时,将获取这些属性。可用属性与服务器的启动选项相同。
注意
Pid 是从
inets:start/[2,3]
返回的 pid。也可以从inets:services/0
和inets:services_info/0
获取,请参阅inets
。
-spec info(Address, Port, Profile) -> HttpInformation when Address :: inet:ip_address() | any, Port :: integer(), Profile :: atom(), Path :: file:name_all(), HttpInformation :: [CommonOption] | [CommunicationOption] | [ModOption] | [LimitOption] | [AdminOption], CommonOption :: {port, non_neg_integer()} | {server_name, string()} | {server_root, Path} | {document_root, Path}, CommunicationOption :: {bind_address, inet:ip_address() | inet:hostname() | any} | {profile, atom()} | {socket_type, ip_comm | {ip_comm, ssl:tls_option() | gen_tcp:option()} | {ssl, ssl:tls_option() | gen_tcp:option()}} | {ipfamily, inet | inet6} | {minimum_bytes_per_second, integer()}, ModOption :: {modules, atom()}, LimitOption :: {customize, atom()} | {disable_chunked_transfer_encoding_send, boolean()} | {keep_alive, boolean()} | {keep_alive_timeout, integer()} | {max_body_size, integer()} | {max_clients, integer()} | {max_header_size, integer()} | {max_content_length, integer()} | {max_uri_size, integer()} | {max_keep_alive_request, integer()} | {max_client_body_chunk, integer()}, AdminOption :: {mime_types, [{MimeType :: string(), Extension :: string()}] | Path} | {mime_type, string()} | {server_admin, string()} | {server_tokens, none | prod | major | minor | minimal | os | full | {private, string()}} | {logger, Options :: list()} | {log_format, common | combined} | {error_log_format, pretty | compact}; (Address, Port, Properties) -> HttpInformation when Address :: inet:ip_address() | any, Port :: integer(), Properties :: [atom()], Path :: file:name_all(), HttpInformation :: [CommonOption] | [CommunicationOption] | [ModOption] | [LimitOption] | [AdminOption], CommonOption :: {port, non_neg_integer()} | {server_name, string()} | {server_root, Path} | {document_root, Path}, CommunicationOption :: {bind_address, inet:ip_address() | inet:hostname() | any} | {profile, atom()} | {socket_type, ip_comm | {ip_comm, ssl:tls_option() | gen_tcp:option()} | {ssl, ssl:tls_option() | gen_tcp:option()}} | {ipfamily, inet | inet6} | {minimum_bytes_per_second, integer()}, ModOption :: {modules, atom()}, LimitOption :: {customize, atom()} | {disable_chunked_transfer_encoding_send, boolean()} | {keep_alive, boolean()} | {keep_alive_timeout, integer()} | {max_body_size, integer()} | {max_clients, integer()} | {max_header_size, integer()} | {max_content_length, integer()} | {max_uri_size, integer()} | {max_keep_alive_request, integer()} | {max_client_body_chunk, integer()}, AdminOption :: {mime_types, [{MimeType :: string(), Extension :: string()}] | Path} | {mime_type, string()} | {server_admin, string()} | {server_tokens, none | prod | major | minor | minimal | os | full | {private, string()}} | {logger, Options :: list()} | {log_format, common | combined} | {error_log_format, pretty | compact}.
等效于 info/4
。
-spec info(Address, Port, Profile, Properties) -> HttpInformation when Address :: inet:ip_address() | any, Port :: integer(), Profile :: atom(), Properties :: [atom()], Path :: file:name_all(), HttpInformation :: [CommonOption] | [CommunicationOption] | [ModOption] | [LimitOption] | [AdminOption], CommonOption :: {port, non_neg_integer()} | {server_name, string()} | {server_root, Path} | {document_root, Path}, CommunicationOption :: {bind_address, inet:ip_address() | inet:hostname() | any} | {profile, atom()} | {socket_type, ip_comm | {ip_comm, ssl:tls_option() | gen_tcp:option()} | {ssl, ssl:tls_option() | gen_tcp:option()}} | {ipfamily, inet | inet6} | {minimum_bytes_per_second, integer()}, ModOption :: {modules, atom()}, LimitOption :: {customize, atom()} | {disable_chunked_transfer_encoding_send, boolean()} | {keep_alive, boolean()} | {keep_alive_timeout, integer()} | {max_body_size, integer()} | {max_clients, integer()} | {max_header_size, integer()} | {max_content_length, integer()} | {max_uri_size, integer()} | {max_keep_alive_request, integer()} | {max_client_body_chunk, integer()}, AdminOption :: {mime_types, [{MimeType :: string(), Extension :: string()}] | Path} | {mime_type, string()} | {server_admin, string()} | {server_tokens, none | prod | major | minor | minimal | os | full | {private, string()}} | {logger, Options :: list()} | {log_format, common | combined} | {error_log_format, pretty | compact}.
获取有关 HTTP 服务器的信息。当仅使用 Address
和 Port
调用时,将获取所有属性。当使用特定属性列表调用时,将获取这些属性。可用属性与服务器的启动选项相同。
注意
Address
必须是 IP 地址,不能是主机名。
-spec reload_config(Config, Mode) -> ok | {error, Reason} | no_return() when Config :: file:name_all() | [{Option, Value}], Mode :: non_disturbing | disturbing | blocked, Option :: atom(), Value :: term(), Reason :: term().
重新加载 HTTP 服务器配置,而无需重启服务器。在重新加载期间,传入的请求会以临时关闭消息响应。
注意
可用属性与服务器的启动选项相同,但不能更改属性
bind_address
和port
。
如果模式是破坏性的,则服务器会被强制阻止,所有正在进行的请求都会终止,并且重新加载会立即开始。如果模式是非破坏性的,则不会接受新连接,但允许正在进行的请求在完成重新加载之前完成。