【问题标题】:erlang response http request in decimal instead of lettererlang响应http请求以十进制而不是字母
【发布时间】:2015-06-15 16:55:39
【问题描述】:

我开始将 Erlang 与 Cowboy 和 Leptus 一起使用来创建 REST API。

所以我只是尝试了一些简单的方法:

myapp_handler.erl

-module(myapp_handler).
-compile({parse_transform, leptus_pt}).
-export([init/3]).
-export([cross_domains/3]).
-export([terminate/4]).
-export([post/3]).

%% Cross Domain Origin
%% It accepts any host for cross-domain requests
cross_domains(_Route, _Req, State) ->
   {['_'], State}.

%% Start
init(_Route, _Req, State) ->
  {ok, State}.

post("/myRequest", Req, State) ->

  Json = "[
    {
      \"test\": \"hello\"
    }
  ]",

  {200, {json, Json}, State}.

%% End
terminate(_Reason, _Route, _Req, _State) ->
   ok.

启动服务器后,我尝试通过 curl 运行 POST 请求:

curl -X POST http://127.0.0.1:8080/myRequest --header "内容类型:文本/json"

请求的答案是:

[91,10,32,32,32,32,123,10,32,32,32,32,32,32,34,116,101,115,116,34,58,32,34,104,101,108,108,111,34,10,32,32,32,32,125,10,32,32,93]

所有数字都是ASCII表中十进制字符的值。但我想知道为什么请求的答案以数字而不是字母显示。我是不是做错了什么?

提前谢谢你

【问题讨论】:

    标签: rest http post erlang cowboy


    【解决方案1】:

    Erlang 字符串是整数列表,所以你得到的正是你应该得到的(嗯,这种数据实际上可能是二进制字符串或列表字符串)。在 shell 中查看响应的奇怪之处在于 shell 认为格式化输出的适当方式是:作为字符串或作为列表。如果有任何 ASCII“控制”字符,或者大于 127 的值,并且它认为它不是 UTF-8 语言环境,那么它只会打印整数。

    如果你这样做,通常你可以很确定地得到字符:

    Response = your_function(YourArgs),
    io:format("Response:~ts~n", [Response]).
    

    而不是仅仅依靠 shell 以默认方式将输出格式化为 stdio(如果对环境有任何不确定性,它总是回退到整数列表)。

    将你的输出粘贴到我的 shell...

    1> Z = [91,10,32,32,32,32,123,10,32,32,32,32,32,32,34,116,101,115,116,34,58,32,34,104,101,108,108,111,34,10,32,32,32,32,125,10,32,32,93].                                                       
    "[\n    {\n      \"test\": \"hello\"\n    }\n  ]"
    2> io:format("Using ~~ts:~n~ts~n~n"                                                 
    2>           "Using ~~tw:~n~tw~n~n"
    2>           "Using ~~tp:~n~tp~n~n",
    2>           [Z, Z, Z]).
    Using ~ts:
    [
        {
          "test": "hello"
        }
      ]
    
    Using ~tw:
    [91,10,32,32,32,32,123,10,32,32,32,32,32,32,34,116,101,115,116,34,58,32,34,104,101,108,108,111,34,10,32,32,32,32,125,10,32,32,93]
    
    Using ~tp:
    "[\n    {\n      \"test\": \"hello\"\n    }\n  ]"
    
    ok
    

    【讨论】:

      【解决方案2】:

      我以前没有使用过 Leptus,但是,让我们看看他们在 Github (https://github.com/s1n4/leptus) 上的 README 中的一个示例 REST 端点:

      get("/", _Req, State) ->
        {<<"Hello, leptus!">>, State};
      
      get("/hi/:name", Req, State) ->
        Status = ok,
        Name = leptus_req:param(Req, name),
        Body = [{<<"say">>, <<"Hi">>}, {<<"to">>, Name}],
        {Status, {json, Body}, State}.
      

      看来,如果您发布一个 {json, Term} 元组,它会自动将您的 Erlang 术语转换为 JSON。因此,与其手动制作 JSON,不如使用:

      post("/myRequest", Req, State) ->
        Json = [{<<"test">>, <<"hello">>}],
        {200, {json, Json}, State}.
      

      Leptus 似乎还希望您的字符串和 JSON 键以及 JSON 字符串值作为二进制文件传入。因此,如果您想返回一个简单的输出字符串,您可以使用以下内容:

      post("/myRequest", Req, State) ->
        {200, <<"hello">>, State}.
      

      通常库将使用二进制文件而不是标准 Erlang 字符串,因为二进制文件比 Erlang 字符串列表更有效。

      【讨论】:

      • 感谢您的回答,它有效!我还有一个问题,当你想在 JSON 文字中放入一个对象数组时?我怎样才能做到这一点?例如:Json = [ { &lt;&lt;"hello"&gt;&gt;, &lt;&lt;"test"&gt;&gt;, [ { {&lt;&lt;"a"&gt;&gt;, &lt;&lt;"b"&gt;&gt;}, {&lt;&lt;"c"&gt;&gt;, &lt;&lt;"d"&gt;&gt;}, {&lt;&lt;"e"&gt;&gt;, &lt;&lt;"f"&gt;&gt;}, {&lt;&lt;"g"&gt;&gt;, &lt;&lt;"h"&gt;&gt;} } ] } ], 但它似乎不起作用。有什么建议吗?
      • 它可能会将 proplists 转换为 JSON 对象。试试Json = [[{&lt;&lt;"hello"&gt;&gt;, &lt;&lt;"test"&gt;&gt;}], [{&lt;&lt;"a"&gt;&gt;, &lt;&lt;"b"&gt;&gt;}, {&lt;&lt;"c"&gt;&gt;, &lt;&lt;"d"&gt;&gt;}, {&lt;&lt;"e"&gt;&gt;, &lt;&lt;"f"&gt;&gt;}, {&lt;&lt;"g"&gt;&gt;, &lt;&lt;"h"&gt;&gt;}]]
      • 我在使用您的代码执行路线时出错:Ranch listener leptus_http had connection process started with cowboy_protocol:start_link/4 at &lt;0.162.0&gt; exit with reason: {{nocatch,{error,invalid_ejson}},[{jiffy,encode,2,[{file,"src/jiffy.erl"},{line,34}]},{leptus_handler,prepare_headers_body,2,[{file,"src/leptus_handler.erl"},{line,411}]},{leptus_handler,handle_response,5,[{file,"src/leptus_handler.erl"},{line,390}]},{leptus_handler,upgrade,4,[{file,"src/leptus_handler.erl"},{line,82}]},{cowboy_protocol,execute,4,[{file,"src/cowboy_protocol.erl"},{line,529}]}]} 有什么建议吗?
      • 看起来 leptus 正在使用 jiffy 进行编码 (github.com/davisp/jiffy)。 Jiffy 似乎期望 Erlang JSON 等效为包含 proplist ({proplist()}) 的单个元素元组。试试这个:{[{[{&lt;&lt;"hello"&gt;&gt;, &lt;&lt;"test"&gt;&gt;}]}, {[{&lt;&lt;"a"&gt;&gt;, &lt;&lt;"b"&gt;&gt;}, {&lt;&lt;"c"&gt;&gt;, &lt;&lt;"d"&gt;&gt;}, {&lt;&lt;"e"&gt;&gt;, &lt;&lt;"f"&gt;&gt;}, {&lt;&lt;"g"&gt;&gt;, &lt;&lt;"h"&gt;&gt;}]}]}.
      • 根据 Erlang 邮件列表的讨论,单元素元组似乎被用来简化 Erlang JSON 表示与列表的模式匹配。这是讨论的链接:erlang.org/pipermail/erlang-questions/2013-July/074756.html.
      猜你喜欢
      • 2016-09-09
      • 2017-03-10
      • 2018-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-30
      • 1970-01-01
      相关资源
      最近更新 更多