Erlang 读取 post 请求
Erlang read post request
我正在尝试构建一个基于 Erlang 的简单 Web 服务器,到目前为止,我能够使用以下代码启动服务器。 tutorial ref
-module(helloworld).
-export([
main/1,
run_server/0,
start/0,
service/3,
]).
main(_) ->
start(),
receive
stop -> ok
end.
run_server() ->
ok = inets:start(),
{ok, _} = inets:start(httpd, [
{modules, [
mod_alias,
mod_auth,
mod_esi,
mod_actions,
mod_cgi,
mod_dir,
mod_get,
mod_head,
mod_log,
mod_disk_log
]},
{port, 8000},
{server_name,"helloworld"},
{server_root,"/tmp"},
{document_root,"."},
{erl_script_alias, {"/erl", [helloworld]}},
{error_log, "error.log"},
{security_log, "security.log"},
{transfer_log, "transfer.log"},
{mime_types,[
{"html","text/html"}, {"css","text/css"}, {"js","application/x-javascript"} ]}
]).
start() -> run_server().
service(SessionID, _Env, _Input) -> mod_esi:deliver(SessionID, [
"Content-Type: text/html\r\n\r\n", "<html><body>Hello, World!</body></html>" ]).
我正在尝试获取响应,但出现权限错误。
You don't have permission to access /erl/hello_world:servie on this server.
我的目标是构建基于 Erlang 的服务器,它可以读取 post 请求并将 post 数据存储在 MYSQL 中。
如果有人可以通过说明或一些代码帮助我启动 Erlang 服务器以读取 POST 请求,那将非常有帮助。
谢谢
您正在调用 inets:start/0 和 inets:start/2,在示例中它只是一个或另一个,不知道这是否会产生影响。
I'm aiming to build Erlang based server which can read post request
and store the post data in MYSQL.
我用 rebar3 创建了一个应用程序:
$ rebar3 new app myserver
然后我指定了mysql-otp as a dependency so that I could use mysql. I basically ignored the OTP app, and I added some source code to start an inets server. See 。
这是我用来启动 inets httpd 服务器、处理请求并将 post 数据插入 mysql 数据库的模块:
my.erl
:
-module(my).
-compile(export_all).
ensure_inets_start() ->
case inets:start() of
ok -> ok;
{error,{already_started,inets}} -> ok
end.
start() ->
ok = my:ensure_inets_start(),
%Construct path to myserver/priv/server.conf:
PrivDir = code:priv_dir(myserver),
ServerConfPath = filename:join(PrivDir, "server.conf"),
{ok, Server} = inets:start(httpd,
[{proplist_file, ServerConfPath}]
),
Server.
stop(Server) ->
ok = inets:stop(httpd, Server).
log(Data) ->
{ok, IoDevice} = file:open(
%"/Users/7stud/erlang_programs/inets_post_request/myserver/logs/mylog.log",
"./logs/mylog.log",
[append]
),
file:write(IoDevice, Data),
file:close(IoDevice).
handle_request(SessionID, Env, Input) ->
Headers = "Content-Type: text/html\r\n\r\n",
Data = [
<<"Hello, ">>,
"esi!\n"
],
log(io_lib:format(
"Inside my:handle_request()\nSessionId=~p\nEnv=~p\nInput=~p\n",
[SessionID, Env, Input]
)),
PostData = list_to_binary(Input),
[NamePair, InfoPair] = binary:split(PostData, <<"&">>),
[<<"name">>, Name] = binary:split(NamePair, <<"=">>),
[<<"info">>, Info] = binary:split(InfoPair, <<"=">>),
do_mysql(Name, Info),
mod_esi:deliver(SessionID, Headers), %Headers must be a string.
mod_esi:deliver(SessionID, Data). %Data can be an iolist.
do_mysql(Name, Info) ->
{ok, MysqlPid} = mysql:start_link(
[{host, "localhost"},
{user, "root"},
{password, ""},
{database, "mydb"}
]
),
%{ok, ColumnNames, Rows} = mysql:query(
% Pid,
% <<"SELECT * FROM people">>),
%io:format("ColumnNames: ~p~nRows: ~p~n", [ColumnNames, Rows]).
ok = mysql:query(
MysqlPid,
"INSERT INTO people (name, info) VALUES (?, ?)", [Name, Info]
).
我将该代码放在我的应用程序的 src
目录中,该目录名为 myserver
。这是我的目录结构:
~/erlang_programs/inets_post_request$ tree myserver
myserver
├── htdocs
├── logs
│ ├── errors.log
│ ├── mylog.log
│ └── requests.log
├── priv
│ └── server.conf
├── rebar.config (created by rebar3)
├── rebar.lock (created by rebar3)
└── src
├── my.erl
├── myserver.app.src (created by rebar3)
├── myserver_app.erl (created by rebar3)
└── myserver_sup.erl (created by rebar3)
(compiling with rebar3 creates all this stuff:)
├── _build
│ └── default
│ └── lib
│ ├── myserver
│ │ ├── ebin
│ │ │ ├── my.beam
│ │ │ ├── myserver.app
│ │ │ ├── myserver_app.beam
│ │ │ └── myserver_sup.beam
│ │ ├── include -> ../../../../include
│ │ ├── priv -> ../../../../priv
│ │ └── src -> ../../../../src
│ └── mysql
│ ├── CHANGELOG.md
│ ├── COPYING
│ ├── COPYING.LESSER
│ ├── Makefile
│ ├── README.md
│ ├── changelog.sh
│ ├── doc
│ │ └── overview.edoc
│ ├── ebin
│ │ ├── mysql.app
│ │ ├── mysql.beam
│ │ ├── mysql_cache.beam
│ │ ├── mysql_encode.beam
│ │ ├── mysql_protocol.beam
│ │ ├── mysql_sock_ssl.beam
│ │ └── mysql_sock_tcp.beam
│ ├── erlang-mk.build.config
│ ├── erlang.mk
│ ├── include
│ │ ├── protocol.hrl
│ │ ├── records.hrl
│ │ └── server_status.hrl
│ ├── priv
│ │ └── edoc-style.css
│ ├── src
│ │ ├── mysql.app.src
│ │ ├── mysql.erl
│ │ ├── mysql_cache.erl
│ │ ├── mysql_encode.erl
│ │ ├── mysql_protocol.erl
│ │ ├── mysql_sock_ssl.erl
│ │ └── mysql_sock_tcp.erl
│ └── test
│ ├── error_logger_acc.erl
│ ├── mock_tcp.erl
│ ├── mysql_encode_tests.erl
│ ├── mysql_protocol_tests.erl
│ ├── mysql_tests.erl
│ ├── ssl
│ │ ├── Makefile
│ │ └── my-ssl.cnf.template
│ ├── ssl_tests.erl
│ └── transaction_tests.erl
这是 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,"./"},
{document_root,"./htdocs"},
{erl_script_alias, {"/erl", [my]} },
{erl_script_nocache, true},
{error_log, "./logs/errors.log"},
{transfer_log, "./logs/requests.log"}
].
然后,运行我做的应用:
~/erlang_programs/inets_post_request/myserver$ rebar3 compile (may not be necessary)
...
...
~/erlang_programs/inets_post_request/myserver$ rebar3 shell (looks like this also will fetch the dependencies, then compile)
===> Verifying dependencies...
===> Compiling myserver
/Users/7stud/erlang_programs/inets_post_request/myserver/_build/default/lib/myserver/src/my.erl:2: Warning: export_all flag enabled - all functions will be exported
Erlang/OTP 20 [erts-9.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V9.2 (abort with ^G)
1> S = my:start().
<0.127.0>
2> httpd:info(S).
[{mime_types,[{"htm","text/html"},{"html","text/html"}]},
{server_name,"httpd_test"},
{erl_script_nocache,true},
{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_post_request/myserver/src"},
{erl_script_alias,{"/erl",[my]}},
{port,55804},
{transfer_log,<0.134.0>},
{error_log,<0.133.0>},
{document_root,"./htdocs"}]
3>
我查看了该输出以获取服务器的端口:55804
,我曾经使用 curl 发送 post 请求:
~$ curl -v --data "name=Kathy&info=xyz" "http://localhost:55804/erl/my:handle_request"
* Trying ::1...
* TCP_NODELAY set
* Connection failed
* connect to ::1 port 55804 failed: Connection refused
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 55804 (#0)
> POST /erl/my:handle_request HTTP/1.1
> Host: localhost:55804
> User-Agent: curl/7.58.0
> Accept: */*
> Content-Length: 19
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 19 out of 19 bytes
< HTTP/1.1 200 OK
< Date: Wed, 09 May 2018 00:10:42 GMT
< Server: inets/6.4.5
< Cache-Control: no-cache
< Pragma: no-cache
< Expires: Wed, 09 May 2018 00:10:42 GMT
< Transfer-Encoding: chunked
< Content-Type: text/html
<
Hello, esi!
* Connection #0 to host localhost left intact
~$
然后我停止了 inets httpd 服务器:
4> my:stop(S).
ok
5>
然后我检查了 mysql 数据库中的新条目:
mysql> select * from people;
+----+-------+------+
| id | name | info |
+----+-------+------+
| 1 | Fred | abc |
| 2 | Alice | xxx |
| 3 | Kathy | xyz |
+----+-------+------+
4 rows in set (0.00 sec)
成功!
这是我的 rebar.config
文件:
{erl_opts, [debug_info]}.
{deps, [
{mysql, {git, "https://github.com/mysql-otp/mysql-otp",
{tag, "1.3.2"}}}
]}.
我对同样写得不好的教程也有同样的问题。最后他们告诉你去:
http://localhost:8081/erl/hello_world:service
然而,URL应该是:
http://localhost:8081/erl/helloworld:service
(注意删除下划线。)
我正在尝试构建一个基于 Erlang 的简单 Web 服务器,到目前为止,我能够使用以下代码启动服务器。 tutorial ref
-module(helloworld).
-export([
main/1,
run_server/0,
start/0,
service/3,
]).
main(_) ->
start(),
receive
stop -> ok
end.
run_server() ->
ok = inets:start(),
{ok, _} = inets:start(httpd, [
{modules, [
mod_alias,
mod_auth,
mod_esi,
mod_actions,
mod_cgi,
mod_dir,
mod_get,
mod_head,
mod_log,
mod_disk_log
]},
{port, 8000},
{server_name,"helloworld"},
{server_root,"/tmp"},
{document_root,"."},
{erl_script_alias, {"/erl", [helloworld]}},
{error_log, "error.log"},
{security_log, "security.log"},
{transfer_log, "transfer.log"},
{mime_types,[
{"html","text/html"}, {"css","text/css"}, {"js","application/x-javascript"} ]}
]).
start() -> run_server().
service(SessionID, _Env, _Input) -> mod_esi:deliver(SessionID, [
"Content-Type: text/html\r\n\r\n", "<html><body>Hello, World!</body></html>" ]).
我正在尝试获取响应,但出现权限错误。
You don't have permission to access /erl/hello_world:servie on this server.
我的目标是构建基于 Erlang 的服务器,它可以读取 post 请求并将 post 数据存储在 MYSQL 中。
如果有人可以通过说明或一些代码帮助我启动 Erlang 服务器以读取 POST 请求,那将非常有帮助。
谢谢
您正在调用 inets:start/0 和 inets:start/2,在示例中它只是一个或另一个,不知道这是否会产生影响。
I'm aiming to build Erlang based server which can read post request and store the post data in MYSQL.
我用 rebar3 创建了一个应用程序:
$ rebar3 new app myserver
然后我指定了mysql-otp as a dependency so that I could use mysql. I basically ignored the OTP app, and I added some source code to start an inets server. See
这是我用来启动 inets httpd 服务器、处理请求并将 post 数据插入 mysql 数据库的模块:
my.erl
:
-module(my).
-compile(export_all).
ensure_inets_start() ->
case inets:start() of
ok -> ok;
{error,{already_started,inets}} -> ok
end.
start() ->
ok = my:ensure_inets_start(),
%Construct path to myserver/priv/server.conf:
PrivDir = code:priv_dir(myserver),
ServerConfPath = filename:join(PrivDir, "server.conf"),
{ok, Server} = inets:start(httpd,
[{proplist_file, ServerConfPath}]
),
Server.
stop(Server) ->
ok = inets:stop(httpd, Server).
log(Data) ->
{ok, IoDevice} = file:open(
%"/Users/7stud/erlang_programs/inets_post_request/myserver/logs/mylog.log",
"./logs/mylog.log",
[append]
),
file:write(IoDevice, Data),
file:close(IoDevice).
handle_request(SessionID, Env, Input) ->
Headers = "Content-Type: text/html\r\n\r\n",
Data = [
<<"Hello, ">>,
"esi!\n"
],
log(io_lib:format(
"Inside my:handle_request()\nSessionId=~p\nEnv=~p\nInput=~p\n",
[SessionID, Env, Input]
)),
PostData = list_to_binary(Input),
[NamePair, InfoPair] = binary:split(PostData, <<"&">>),
[<<"name">>, Name] = binary:split(NamePair, <<"=">>),
[<<"info">>, Info] = binary:split(InfoPair, <<"=">>),
do_mysql(Name, Info),
mod_esi:deliver(SessionID, Headers), %Headers must be a string.
mod_esi:deliver(SessionID, Data). %Data can be an iolist.
do_mysql(Name, Info) ->
{ok, MysqlPid} = mysql:start_link(
[{host, "localhost"},
{user, "root"},
{password, ""},
{database, "mydb"}
]
),
%{ok, ColumnNames, Rows} = mysql:query(
% Pid,
% <<"SELECT * FROM people">>),
%io:format("ColumnNames: ~p~nRows: ~p~n", [ColumnNames, Rows]).
ok = mysql:query(
MysqlPid,
"INSERT INTO people (name, info) VALUES (?, ?)", [Name, Info]
).
我将该代码放在我的应用程序的 src
目录中,该目录名为 myserver
。这是我的目录结构:
~/erlang_programs/inets_post_request$ tree myserver
myserver
├── htdocs
├── logs
│ ├── errors.log
│ ├── mylog.log
│ └── requests.log
├── priv
│ └── server.conf
├── rebar.config (created by rebar3)
├── rebar.lock (created by rebar3)
└── src
├── my.erl
├── myserver.app.src (created by rebar3)
├── myserver_app.erl (created by rebar3)
└── myserver_sup.erl (created by rebar3)
(compiling with rebar3 creates all this stuff:)
├── _build
│ └── default
│ └── lib
│ ├── myserver
│ │ ├── ebin
│ │ │ ├── my.beam
│ │ │ ├── myserver.app
│ │ │ ├── myserver_app.beam
│ │ │ └── myserver_sup.beam
│ │ ├── include -> ../../../../include
│ │ ├── priv -> ../../../../priv
│ │ └── src -> ../../../../src
│ └── mysql
│ ├── CHANGELOG.md
│ ├── COPYING
│ ├── COPYING.LESSER
│ ├── Makefile
│ ├── README.md
│ ├── changelog.sh
│ ├── doc
│ │ └── overview.edoc
│ ├── ebin
│ │ ├── mysql.app
│ │ ├── mysql.beam
│ │ ├── mysql_cache.beam
│ │ ├── mysql_encode.beam
│ │ ├── mysql_protocol.beam
│ │ ├── mysql_sock_ssl.beam
│ │ └── mysql_sock_tcp.beam
│ ├── erlang-mk.build.config
│ ├── erlang.mk
│ ├── include
│ │ ├── protocol.hrl
│ │ ├── records.hrl
│ │ └── server_status.hrl
│ ├── priv
│ │ └── edoc-style.css
│ ├── src
│ │ ├── mysql.app.src
│ │ ├── mysql.erl
│ │ ├── mysql_cache.erl
│ │ ├── mysql_encode.erl
│ │ ├── mysql_protocol.erl
│ │ ├── mysql_sock_ssl.erl
│ │ └── mysql_sock_tcp.erl
│ └── test
│ ├── error_logger_acc.erl
│ ├── mock_tcp.erl
│ ├── mysql_encode_tests.erl
│ ├── mysql_protocol_tests.erl
│ ├── mysql_tests.erl
│ ├── ssl
│ │ ├── Makefile
│ │ └── my-ssl.cnf.template
│ ├── ssl_tests.erl
│ └── transaction_tests.erl
这是 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,"./"},
{document_root,"./htdocs"},
{erl_script_alias, {"/erl", [my]} },
{erl_script_nocache, true},
{error_log, "./logs/errors.log"},
{transfer_log, "./logs/requests.log"}
].
然后,运行我做的应用:
~/erlang_programs/inets_post_request/myserver$ rebar3 compile (may not be necessary)
...
...
~/erlang_programs/inets_post_request/myserver$ rebar3 shell (looks like this also will fetch the dependencies, then compile)
===> Verifying dependencies...
===> Compiling myserver
/Users/7stud/erlang_programs/inets_post_request/myserver/_build/default/lib/myserver/src/my.erl:2: Warning: export_all flag enabled - all functions will be exported
Erlang/OTP 20 [erts-9.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V9.2 (abort with ^G)
1> S = my:start().
<0.127.0>
2> httpd:info(S).
[{mime_types,[{"htm","text/html"},{"html","text/html"}]},
{server_name,"httpd_test"},
{erl_script_nocache,true},
{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_post_request/myserver/src"},
{erl_script_alias,{"/erl",[my]}},
{port,55804},
{transfer_log,<0.134.0>},
{error_log,<0.133.0>},
{document_root,"./htdocs"}]
3>
我查看了该输出以获取服务器的端口:55804
,我曾经使用 curl 发送 post 请求:
~$ curl -v --data "name=Kathy&info=xyz" "http://localhost:55804/erl/my:handle_request"
* Trying ::1...
* TCP_NODELAY set
* Connection failed
* connect to ::1 port 55804 failed: Connection refused
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 55804 (#0)
> POST /erl/my:handle_request HTTP/1.1
> Host: localhost:55804
> User-Agent: curl/7.58.0
> Accept: */*
> Content-Length: 19
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 19 out of 19 bytes
< HTTP/1.1 200 OK
< Date: Wed, 09 May 2018 00:10:42 GMT
< Server: inets/6.4.5
< Cache-Control: no-cache
< Pragma: no-cache
< Expires: Wed, 09 May 2018 00:10:42 GMT
< Transfer-Encoding: chunked
< Content-Type: text/html
<
Hello, esi!
* Connection #0 to host localhost left intact
~$
然后我停止了 inets httpd 服务器:
4> my:stop(S).
ok
5>
然后我检查了 mysql 数据库中的新条目:
mysql> select * from people;
+----+-------+------+
| id | name | info |
+----+-------+------+
| 1 | Fred | abc |
| 2 | Alice | xxx |
| 3 | Kathy | xyz |
+----+-------+------+
4 rows in set (0.00 sec)
成功!
这是我的 rebar.config
文件:
{erl_opts, [debug_info]}.
{deps, [
{mysql, {git, "https://github.com/mysql-otp/mysql-otp",
{tag, "1.3.2"}}}
]}.
我对同样写得不好的教程也有同样的问题。最后他们告诉你去:
http://localhost:8081/erl/hello_world:service
然而,URL应该是:
http://localhost:8081/erl/helloworld:service
(注意删除下划线。)