Erlang iNet httpd:Can';无法使用简单的esi脚本
下面是我用来配置httpd服务器的proplist_文件:Erlang iNet httpd:Can';无法使用简单的esi脚本,erlang,inets,Erlang,Inets,下面是我用来配置httpd服务器的proplist_文件: [ {modules, [ mod_alias, mod_actions, mod_cgi, mod_get, mod_esi, mod_log ]}, {bind_address, "localhost"}, {port,0}, {server_name,"httpd_test"}, {server_root,"/Users/7stud/erlang_progr
[
{modules, [
mod_alias,
mod_actions,
mod_cgi,
mod_get,
mod_esi,
mod_log
]},
{bind_address, "localhost"},
{port,0},
{server_name,"httpd_test"},
{server_root,"/Users/7stud/erlang_programs/inets_proj"},
{document_root,"./htdocs"},
{script_alias, {"/cgi-bin/", "/Users/7stud/erlang_programs/inets_proj/cgi-bin/"} },
{erl_script_alias, {"/cgi-bin/example", [httpd_example]} },
{erl_script_nocache, true},
{error_log, "./errors.log"},
{transfer_log, "./requests.log"}
].
对于esi脚本,密钥属性为:
{erl_script_alias, {"/cgi-bin/example", [httpd_example]} }
根据报告:
ESI属性-需要mod_ESI
{erl\u脚本\u别名,{URLPath,[AllowedModule]}URLPath=string()和AllowedModule=atom()。erl_脚本_别名标记所有URL 将url路径匹配为erl方案脚本。匹配的URL映射到 特定模块和功能,例如:
{erl_script_alias, {"/cgi-bin/example", [httpd_example]}}
请求
http://your.server.org/cgi-bin/example/httpd_example:yahoo
将参考
例如:yahoo/3,或者,如果不存在,
httpd_示例:yahoo/2和
http://your.server.org/cgi-bin/example/other:yahoo
将不会被删除
允许执行
我的目录结构是:
~/erlang_programs$ tree inets_proj/
inets_proj/
├── cgi-bin
│ ├── 1.pl
│ ├── example
│ │ ├── httpd_example.beam
│ │ └── httpd_example.erl
│ ├── httpd_example.beam
│ └── httpd_example.erl
├── cl.beam
├── cl.erl
├── errors.log
├── htdocs
│ └── file1.txt
├── httpd_example.beam
├── httpd_example.erl
├── mylog.log
├── requests.log
├── s.beam
├── s.erl
└── server.conf
我不确定将httpd_示例
模块放在哪里,所以我把它放在了几个地方
esi_mod.erl:
-module(esi_mod).
-compile(export_all).
log(Data) ->
{ok, IoDevice} = file:open(
"/Users/7stud/erlang_programs/inets_proj/mylog.log",
[append]
),
ok = file:write(IoDevice, Data),
file:close(IoDevice).
get_data(SessionID, _Env, _Input) ->
Headers = "Content-Type: text/html\r\n\r\n",
Data = "Hello, esi",
log(["--Inside esi_mod:get_data() ~n"]),
ok = mod_esi:deliver(SessionID, Headers), %Headers must be a string.
ok = mod_esi:deliver(SessionID, Data). %Data can be an iolist.
以下是shell中报告的服务器信息:
$ erl
Erlang/OTP 20 [erts-9.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.2 (abort with ^G)
1> c(s).
s.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,s}
2> S = s:start().
<0.86.0>
3> httpd:info(S).
[{mime_types,[{"htm","text/html"},{"html","text/html"}]},
{server_name,"httpd_test"},
{erl_script_nocache,true},
{script_alias,{"/cgi-bin/",
"/Users/7stud/erlang_programs/inets_proj/cgi-bin/"}},
{bind_address,{127,0,0,1}},
{modules,[mod_alias,mod_actions,mod_cgi,mod_get,mod_esi,
mod_log]},
{server_root,"/Users/7stud/erlang_programs/inets_proj"},
{erl_script_alias,{"/cgi-bin/example",[httpd_example]}},
{port,64470},
{transfer_log,<0.93.0>},
{error_log,<0.92.0>},
{document_root,"./htdocs"}]
4>
~/erlang_programs/inets_proj$ erl
Erlang/OTP 20 [erts-9.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.2 (abort with ^G)
1> c(s).
s.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,s}
2> S = s:start().
<0.86.0>
3> httpd:info(S).
[{mime_types,[{"htm","text/html"},{"html","text/html"}]},
{server_name,"httpd_test"},
{erl_script_nocache,true},
{script_alias,{"/cgi-bin/",
"/Users/7stud/erlang_programs/inets_proj/cgi-bin/"}},
{bind_address,{127,0,0,1}},
{modules,[mod_alias,mod_actions,mod_esi,mod_cgi,mod_get,
mod_log]},
{server_root,"/Users/7stud/erlang_programs/inets_proj"},
{erl_script_alias,{"/erl",[mymod]}},
{port,59202},
{transfer_log,<0.93.0>},
{error_log,<0.92.0>},
{document_root,"./htdocs"}]
4>
已转换为:
./htdocs/cgi-bin/example/httpd_example:get_data
这意味着请求路径被附加到
/htdocs
。嗯???好吧,我有办法了。首先,当我四处搜索时,我偶然发现:
这就是我迄今为止使用的最伟大的erlang“工具”:
退出erlang shell时未清除的命令历史记录
您可以按照此处的说明安装/启用它:
回到手头的问题:
1) 我发现httpd模块的顺序很重要mod_esi
必须在mod_get
之前:
server.conf:
[
{modules, [
mod_alias,
mod_actions,
mod_esi,
mod_cgi,
mod_get,
mod_log
]},
{bind_address, "localhost"},
{port,0},
{server_name,"httpd_test"},
{server_root,"/Users/7stud/erlang_programs/inets_proj"},
{document_root,"./htdocs"},
{script_alias, {"/cgi-bin/", "/Users/7stud/erlang_programs/inets_proj/cgi-bin/"} },
{erl_script_alias, {"/erl", [mymod]} },
{erl_script_nocache, true},
{error_log, "./errors.log"},
{transfer_log, "./requests.log"}
].
在获得正确的模块顺序后,由于奇怪的转换路径,我停止获取“未找到文件”错误
2) esi模块的代码必须位于server\u root
目录中。我的esi模块的名称是mymod.erl
:
~/erlang_programs$ tree inets_proj/
inets_proj/
├── cgi-bin
│ ├── 1.pl
│ ├── example
│ │ ├── httpd_example.beam
│ │ └── httpd_example.erl
│ ├── httpd_example.beam
│ └── httpd_example.erl
├── cl.beam
├── cl.erl
├── errors.log
├── htdocs
│ └── file1.txt
├── mylog.log
├── mymod.beam
├── mymod.erl
├── requests.log
├── s.beam
├── s.erl
├── server.conf
├── xhttpd_example.beam
└── xhttpd_example.erl
3) 因为我指明:
{erl_script_alias, {"/erl", [mymod]} }
我需要使用的url是:
http://localhost:57867/erl/mymod:get_data
端口必须与服务器的端口匹配。正确的路径是在erl_script_alias属性加上/modulename:funcname
或/modulename/funcname
中指定的任何路径
这里是mymod.erl:
-module(mymod).
-export([get_data/3]).
log(Data) ->
{ok, IoDevice} = file:open(
"/Users/7stud/erlang_programs/inets_proj/mylog.log",
[append]
),
file:write(IoDevice, Data),
file:close(IoDevice).
get_data(SessionID, Env, Input) ->
Headers = "Content-Type: text/html\r\n\r\n",
Data = [
<<"Hello, ">>,
"esi!\n"
],
log(io_lib:format(
"Inside mymod:get_data()\nSessionId=~p\nEnv=~p\nInput=~p\n",
[SessionID, Env, Input]
)),
mod_esi:deliver(SessionID, Headers), %Headers must be a string.
mod_esi:deliver(SessionID, Data). %Data can be an iolist.
~/erlang_programs/inets_proj$ erlc mymod.erl
~/erlang_programs/inets_proj$
每次更改mymod.erl后,都必须重新编译,然后重新启动服务器。如果这能起作用,情况会更简单:
5> httpd:reload_config("server.conf", disturbing).
{error,{missing_property,server_name}}
但是,即使我的配置文件指定了一个服务器名称属性,我也会得到这个错误
5) 我建议您通过在模块列表中包括mod_log
并指定属性来记录错误:
{error_log, "./errors.log"}
然后检查该文件,查看请求失败时发生的任何反馈
6) 在我不知道的情况下调用我的自定义log()方法(以便将一些信息写入文件)时,log()方法导致异常,导致服务器拒绝请求并在error.log中输入模块遍历失败的消息
[Timestamp], module traverse failed: mod_esi:do =>
Error Type: exit
Error: {mod_esi_linked_process_died,<0.97.0>,normal}
Stack trace: [{mod_esi,receive_headers,1,[{file,"mod_esi.erl"},{line,428}]},
{mod_esi,deliver_webpage_chunk,3,
[{file,"mod_esi.erl"},{line,389}]},
{mod_esi,erl_scheme_webpage_chunk,5,
[{file,"mod_esi.erl"},{line,380}]},
{mod_esi,generate_webpage,7,
[{file,"mod_esi.erl"},{line,314}]},
{httpd_response,traverse_modules,2,
[{file,"httpd_response.erl"},{line,77}]},
{httpd_response,generate_and_send_response,1,
[{file,"httpd_response.erl"},{line,44}]},
{httpd_request_handler,handle_response,1,
[{file,"httpd_request_handler.erl"},{line,655}]},
{gen_server,try_dispatch,4,
[{file,"gen_server.erl"},{line,616}]}]
8) 下面是一些使用curl的示例请求
shell中的服务器信息:
$ erl
Erlang/OTP 20 [erts-9.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.2 (abort with ^G)
1> c(s).
s.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,s}
2> S = s:start().
<0.86.0>
3> httpd:info(S).
[{mime_types,[{"htm","text/html"},{"html","text/html"}]},
{server_name,"httpd_test"},
{erl_script_nocache,true},
{script_alias,{"/cgi-bin/",
"/Users/7stud/erlang_programs/inets_proj/cgi-bin/"}},
{bind_address,{127,0,0,1}},
{modules,[mod_alias,mod_actions,mod_cgi,mod_get,mod_esi,
mod_log]},
{server_root,"/Users/7stud/erlang_programs/inets_proj"},
{erl_script_alias,{"/cgi-bin/example",[httpd_example]}},
{port,64470},
{transfer_log,<0.93.0>},
{error_log,<0.92.0>},
{document_root,"./htdocs"}]
4>
~/erlang_programs/inets_proj$ erl
Erlang/OTP 20 [erts-9.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.2 (abort with ^G)
1> c(s).
s.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,s}
2> S = s:start().
<0.86.0>
3> httpd:info(S).
[{mime_types,[{"htm","text/html"},{"html","text/html"}]},
{server_name,"httpd_test"},
{erl_script_nocache,true},
{script_alias,{"/cgi-bin/",
"/Users/7stud/erlang_programs/inets_proj/cgi-bin/"}},
{bind_address,{127,0,0,1}},
{modules,[mod_alias,mod_actions,mod_esi,mod_cgi,mod_get,
mod_log]},
{server_root,"/Users/7stud/erlang_programs/inets_proj"},
{erl_script_alias,{"/erl",[mymod]}},
{port,59202},
{transfer_log,<0.93.0>},
{error_log,<0.92.0>},
{document_root,"./htdocs"}]
4>
~/erlang\u程序/inets\u项目$erl
Erlang/OTP 20[erts-9.2][source][64位][smp:4:4][ds:4:4:10][async threads:10][hipe][kernel poll:false]
Eshell V9.2(使用^G中止)
1> 丙(s)。
s、 erl:2:警告:已启用导出\u所有标志-将导出所有功能
{好的,s}
2> S=S:start()。
3> httpd:信息。
[{mime_类型,[{“htm”,“text/html”},{“html”,“text/html”}]},
{server_name,“httpd_test”},
{erl_script_nocache,true},
{script_别名,{”/cgi-bin/“,
“/Users/7stud/erlang_programs/inets_proj/cgi bin/”},
{bind_地址,{127,0,0,1}},
{模块,[mod_别名,mod_操作,mod_esi,mod_cgi,mod_get,
mod_log]},
{server_root,“/Users/7stud/erlang_programs/inets_proj”},
{erl_脚本_别名,{“/erl”,[mymod]},
{port,59202},
{传输日志,},
{错误日志,},
{document_root,“./htdocs”}]
4>
请求1(esi get请求):
~$curl-v”http://localhost:57867/erl/mymod:get_data"
*正在尝试127.0.0.1。。。
*TCP_节点集
*已连接到本地主机(127.0.0.1)端口57867(#0)
>GET/erl/mymod:GET_data HTTP/1.1
>主机:本地主机:57867
>用户代理:curl/7.58.0
>接受:*/*
>
mylog.log:
~/erlang_programs/inets_proj$ cat mylog.log
...
...
Inside mymod:get_data()
SessionId=<0.99.0>
Env=[{server_software,"inets/6.4.5"},
{server_name,"httpd_test"},
{host_name,"ChristophersMBP"},
{gateway_interface,"CGI/1.1"},
{server_protocol,"HTTP/1.1"},
{server_port,59202},
{request_method,"GET"},
{remote_addr,"127.0.0.1"},
{peer_cert,undefined},
{script_name,"/erl/mymod:get_data"},
{http_host,"localhost:59202"},
{http_user_agent,"curl/7.58.0"},
{http_accept,"*/*"}]
Input=[]
-------
~/erlang_programs/inets_proj$ cat mylog.log
...
...
Inside mymod:get_data()
SessionId=<0.105.0>
Env=[{server_software,"inets/6.4.5"},
{server_name,"httpd_test"},
{host_name,"ChristophersMBP"},
{gateway_interface,"CGI/1.1"},
{server_protocol,"HTTP/1.1"},
{server_port,59202},
{request_method,"GET"},
{remote_addr,"127.0.0.1"},
{peer_cert,undefined},
{script_name,"/erl/mymod:get_data?a=1&b=2"},
{http_host,"localhost:59202"},
{http_user_agent,"curl/7.58.0"},
{http_accept,"*/*"},
{query_string,"a=1&b=2"}]
Input="a=1&b=2"
Inside mymod:get_data()
SessionId=<0.108.0>
Env=[{server_software,"inets/6.4.5"},
{server_name,"httpd_test"},
{host_name,"ChristophersMBP"},
{gateway_interface,"CGI/1.1"},
{server_protocol,"HTTP/1.1"},
{server_port,59202},
{request_method,"POST"},
{remote_addr,"127.0.0.1"},
{peer_cert,undefined},
{script_name,"/erl/mymod:get_data"},
{http_host,"localhost:59202"},
{http_user_agent,"curl/7.58.0"},
{http_accept,"*/*"},
{http_content_length,"7"},
{http_content_type,"application/x-www-form-urlencoded"}]
Input="a=1&b=2"
-------
~/erlang\u程序/inets\u项目$cat mylog.log
...
...
mymod内部:获取_数据()
会话ID=
Env=[{server_software,“inets/6.4.5”},
{server_name,“httpd_test”},
{主机名,“ChristophersMBP”},
{网关接口,“CGI/1.1”},
{server_protocol,“HTTP/1.1”},
{server_port,59202},
{request_方法,“GET”},
{远程地址,“127.0.0.1”},
{对等证书,未定义},
{script_name,“/erl/mymod:get_data”},
{http_host,“localhost:59202”},
{http_user_agent,“curl/7.58.0”},
{http_accept,“*/*”}]
输入=[]
-------
请求2(带查询字符串的esi get请求):
~$curl-v”http://localhost:59202/erl/mymod:get_data?a=1&b=2"
*正在尝试127.0.0.1。。。
*TCP_节点集
*已连接到本地主机(127.0.0.1)端口59202(#0)
>GET/erl/mymod:GET_数据?a=1&b=2http/1.1
>主机:localhost:59202
>用户代理:curl/7.58.0
>接受:*/*
>
mylog.log:
~/erlang_programs/inets_proj$ cat mylog.log
...
...
Inside mymod:get_data()
SessionId=<0.99.0>
Env=[{server_software,"inets/6.4.5"},
{server_name,"httpd_test"},
{host_name,"ChristophersMBP"},
{gateway_interface,"CGI/1.1"},
{server_protocol,"HTTP/1.1"},
{server_port,59202},
{request_method,"GET"},
{remote_addr,"127.0.0.1"},
{peer_cert,undefined},
{script_name,"/erl/mymod:get_data"},
{http_host,"localhost:59202"},
{http_user_agent,"curl/7.58.0"},
{http_accept,"*/*"}]
Input=[]
-------
~/erlang_programs/inets_proj$ cat mylog.log
...
...
Inside mymod:get_data()
SessionId=<0.105.0>
Env=[{server_software,"inets/6.4.5"},
{server_name,"httpd_test"},
{host_name,"ChristophersMBP"},
{gateway_interface,"CGI/1.1"},
{server_protocol,"HTTP/1.1"},
{server_port,59202},
{request_method,"GET"},
{remote_addr,"127.0.0.1"},
{peer_cert,undefined},
{script_name,"/erl/mymod:get_data?a=1&b=2"},
{http_host,"localhost:59202"},
{http_user_agent,"curl/7.58.0"},
{http_accept,"*/*"},
{query_string,"a=1&b=2"}]
Input="a=1&b=2"
Inside mymod:get_data()
SessionId=<0.108.0>
Env=[{server_software,"inets/6.4.5"},
{server_name,"httpd_test"},
{host_name,"ChristophersMBP"},
{gateway_interface,"CGI/1.1"},
{server_protocol,"HTTP/1.1"},
{server_port,59202},
{request_method,"POST"},
{remote_addr,"127.0.0.1"},
{peer_cert,undefined},
{script_name,"/erl/mymod:get_data"},
{http_host,"localhost:59202"},
{http_user_agent,"curl/7.58.0"},
{http_accept,"*/*"},
{http_content_length,"7"},
{http_content_type,"application/x-www-form-urlencoded"}]
Input="a=1&b=2"
-------
~/erlang\u程序/inets\u项目$cat mylog.log
...
...
mymod内部:获取_数据()
会话ID=
Env=[{server_software,“inets/6.4.5”},
{server_name,“httpd_test”},
{主机名,“ChristophersMBP”},
{网关接口,“CGI/1.1”},
{server_protocol,“HTTP/1.1”},
{server_port,59202},
{request_方法,“GET”},
{远程添加
Inside mymod:get_data()
SessionId=<0.108.0>
Env=[{server_software,"inets/6.4.5"},
{server_name,"httpd_test"},
{host_name,"ChristophersMBP"},
{gateway_interface,"CGI/1.1"},
{server_protocol,"HTTP/1.1"},
{server_port,59202},
{request_method,"POST"},
{remote_addr,"127.0.0.1"},
{peer_cert,undefined},
{script_name,"/erl/mymod:get_data"},
{http_host,"localhost:59202"},
{http_user_agent,"curl/7.58.0"},
{http_accept,"*/*"},
{http_content_length,"7"},
{http_content_type,"application/x-www-form-urlencoded"}]
Input="a=1&b=2"
-------
~$ curl -v "http://localhost:59202/cgi-bin/1.pl"
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 59202 (#0)
> GET /cgi-bin/1.pl HTTP/1.1
> Host: localhost:59202
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Wed, 28 Feb 2018 13:41:43 GMT
< Server: inets/6.4.5
< Transfer-Encoding: chunked
< Content-Type: text/html
<
Hello, Perl.
* Connection #0 to host localhost left intact
~$ curl -v "http://localhost:59202/file1.txt"
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 59202 (#0)
> GET /file1.txt HTTP/1.1
> Host: localhost:59202
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Wed, 28 Feb 2018 13:42:15 GMT
< Server: inets/6.4.5
< Content-Type: text/plain
< Etag: nCZT0114
< Content-Length: 14
< Last-Modified: Mon, 26 Feb 2018 02:51:52 GMT
<
Hello, world!
* Connection #0 to host localhost left intact