查看源代码 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 服务器在运行时动态启动,则仍然可以指定文件,也可以指定完整的属性列表。

  • {proplist_file, path()}
    如果定义了此属性,Inets 会期望在此文件中找到所有其他定义的属性。该文件必须包含在强制属性下列出的所有属性。

注意

注意:在 OTP-23 中,已删除对具有 Apache 语法的旧版配置文件的支持。

强制属性

  • {port, integer()}
    HTTP 服务器监听的端口。如果将端口指定为零,则会选择一个任意的可用端口,并且可以使用函数 httpd:info/2 来确定选择了哪个端口。

  • {server_root, path()}
    定义服务器的主目录,其中可以存储日志文件等。在其他属性中指定的相对路径是指此目录。

  • {document_root, path()}
    定义 HTTP 服务器上可用的文档的顶级目录。

通信属性

  • {bind_address, ip_address() | hostname() | any}
    默认值为 any

  • {server_name, string()}
    服务器的名称,通常是完全限定域名。

    如果未给出,则默认为 net_adm:localhost()

  • {profile, atom()}
    bind_addressport 一起使用,以唯一标识 HTTP 服务器。这在虚拟化环境中很有用,在虚拟化环境中,可能存在多个具有相同 bind_address 和端口的服务器。如果未显式设置此属性,则假定 bind_addressport 唯一标识了 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_body_size, integer()}
    限制 HTTP 请求的消息主体的大小。默认值是没有限制。

  • {max_clients, integer()}
    限制可以支持的并发请求数。默认值为 150

  • {max_header_size, integer()}
    限制 HTTP 请求的消息头的大小。默认值为 10240

  • {max_content_length, integer()}
    传入请求中的最大 content-length,以字节为单位。内容大于此值的请求将以状态 413 响应。默认值为 100000000 (100 MB)。

  • {max_uri_size, integer()}
    限制 HTTP 请求 URI 的大小。默认值是没有限制。

  • {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 服务器中 ServerIDmy_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_logmod_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_logmod_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.htmlhttp://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.11150.100.23 子网上的所有机器都允许访问。

  • {deny_from, all | [RegxpHostString]}
    定义一组拒绝访问给定目录的主机,例如:

    {deny_from, ["123.34.56.11", "150.100.23"]}

    主机 123.34.56.11150.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 服务器启动后更改密码。否则,它将以明文形式写入配置文件。

  • {require_user, [string()]}
    定义使用秘密密码授予访问给定目录的用户。

  • {require_group, [string()]}
    定义使用秘密密码授予访问给定目录的用户。

安全属性 - 需要 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_commssl,具体取决于 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,则与客户端的连接是一个持久连接,并且在请求得到服务时不会关闭。

另请参阅

RFC 2616inetsssl

总结

回调

当有效请求到达 httpd 时,它会在每个模块中调用 do/1,该模块由 Module 的配置选项定义。该函数可以为其他模块生成数据,或生成可以发送回客户端的响应。

httpd 关闭时,它会尝试在每个 Erlang Web 服务器回调模块中执行 remove/1。程序员可以使用此函数来清理在 store 函数中创建的资源。

在将配置选项保存到内部数据库之前,检查配置选项的有效性。此函数还可以具有副作用,即设置配置选项所隐含的必要额外资源。它还可以通过更改选项的值来解决配置选项之间可能的依赖关系。此函数仅需要为此特定回调模块实现的选项设置子句。

Web 服务器 API 帮助函数

parse_query/1 将传入的数据解析为 erleval 脚本(请参阅 mod_esi),格式遵循标准的 URL 格式,即 '+' 变成 '空格',并解码十六进制字符 (%xx)。

函数

等效于 info/2

获取有关 HTTP 服务器的信息。当仅使用 pid 调用时,将获取所有属性。当使用特定属性列表调用时,将获取这些属性。可用属性与服务器的启动选项相同。

等效于 info/4

获取有关 HTTP 服务器的信息。当仅使用 AddressPort 调用时,将获取所有属性。当使用特定属性列表调用时,将获取这些属性。可用属性与服务器的启动选项相同。

重新加载 HTTP 服务器配置,而无需重启服务器。在重新加载期间,传入的请求会以临时关闭消息响应。

类型

此类型的链接

property()

查看源码 (未导出)
-type property() :: atom().
-type socket_type() :: ip_comm | ssl.

回调

-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,则表示出现问题,服务器将通过关闭连接向客户端发出信号。

此回调的链接

remove(ConfigDB)

查看源码 (可选)
-callback remove(ConfigDB) -> ok | {error, Reason} when ConfigDB :: ets:tid(), Reason :: term().

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 辅助函数

此函数的链接

parse_query(QueryString)

查看源码
此函数已弃用。httpd:parse_query/1 已弃用;请改用 uri_string:dissect_query/1。
-spec parse_query(QueryString) -> QueryList | uri_string:error()
                     when
                         QueryString :: string(),
                         QueryList :: [{unicode:chardata(), unicode:chardata() | true}].

parse_query/1 将传入的数据解析为 erleval 脚本(请参阅 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/0inets: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

此函数的链接

info(Address, Port, Profile, Properties)

查看源码 (自 OTP 18.0 起)
-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 服务器的信息。当仅使用 AddressPort 调用时,将获取所有属性。当使用特定属性列表调用时,将获取这些属性。可用属性与服务器的启动选项相同。

注意

Address 必须是 IP 地址,不能是主机名。

此函数的链接

reload_config(Config, Mode)

查看源码
-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_addressport

如果模式是破坏性的,则服务器会被强制阻止,所有正在进行的请求都会终止,并且重新加载会立即开始。如果模式是非破坏性的,则不会接受新连接,但允许正在进行的请求在完成重新加载之前完成。