Erlang阅读帖子请求 [英] Erlang read post request

查看:71
本文介绍了Erlang阅读帖子请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试基于Erlang构建一个简单的Web服务器,到目前为止,我可以使用以下代码启动服务器。 教程参考

I'm trying to build a simple web server based on Erlang, so far I'm able to start a server with below code. 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>" ]).

我正在尝试获取响应,但遇到权限错误。

I'm trying to get the response but getting the permission error.


您无权访问此服务器上的/ erl / hello_world:servie。

You don't have permission to access /erl/hello_world:servie on this server.

我的目标是建立基于Erlang的服务器,该服务器可以读取发布请求并将发布数据存储在MYSQL中。

I'm aiming to build Erlang based server which can read post request and store the post data in MYSQL.

如果有人可以帮助我进行说明或使用一些代码来启动Erlang服务器以读取POST请求,这将非常有用。

If anyone can help me with instructions or with some code to start the Erlang server for reading POST request that will be so helpful.

谢谢

推荐答案


我的目标是建立基于Erlang的服务器,该服务器可以读取发布请求
并将发布数据存储在MYSQL中。

I'm aiming to build Erlang based server which can read post request and store the post data in MYSQL.

我用 rebar3 创建了一个应用程序:

I used rebar3 to create an app:

$ rebar3 new app myserver

然后我指定了 mysql-otp 作为依赖项,以便可以使用mysql。我基本上忽略了OTP应用程序,并添加了一些源代码来启动inets服务器。请参见此处

Then I specified 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 here.

这是我用来启动inets httpd服务器,处理请求并将发布数据插入mysql db的模块:

Here's the module I used to start the inets httpd server, handle the request, and insert the post data into a mysql db:

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 。这是我的目录结构:

I put that code in the src directory of my app, which was named myserver. Here is my directory structure:

~/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"}
].

然后,运行我执行的应用程序:

Then, to run the app I did:

~/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发送过一个发帖请求:

I looked at that output to get the server's port: 55804, which I used to send a post request with curl:

~$ 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服务器:

Then I stopped the inets httpd server:

4> my:stop(S).
ok

5> 

然后我检查了mysql db中是否有新条目:

Then I checked the mysql db for a new entry:

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"}}}
]}.

这篇关于Erlang阅读帖子请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆