erlang response HTTP-запрос в десятичном формате вместо буквы

Я начинаю использовать 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.

После запуска сервера я попытался запустить POST-запрос через curl:

curl -X POST http://127.0.0.1:8080/myRequest --header "Content-Type: текст/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. Но интересно, почему ответ на запрос отображается цифрами, а не буквами. Я сделал что-то не так?

заранее спасибо


person Jean Lebrument    schedule 10.04.2015    source источник


Ответы (2)


Я раньше не использовал Leptus, но давайте взглянем на пример конечной точки REST из их README на Github (https://github.com/s1n4/leptus):

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.

person nu-ex    schedule 10.04.2015
comment
Спасибо за ответ, работает! У меня есть еще один вопрос, когда вы хотите поместить массив объектов в литерал JSON? Как я могу этого добиться? Например: Json = [ { <<"hello">>, <<"test">>, [ { {<<"a">>, <<"b">>}, {<<"c">>, <<"d">>}, {<<"e">>, <<"f">>}, {<<"g">>, <<"h">>} } ] } ], Но это не работает. Какие-либо предложения? - person Jean Lebrument; 11.04.2015
comment
Вероятно, он преобразует пролисты в объекты JSON. Попробуйте Json = [[{<<"hello">>, <<"test">>}], [{<<"a">>, <<"b">>}, {<<"c">>, <<"d">>}, {<<"e">>, <<"f">>}, {<<"g">>, <<"h">>}]]. - person nu-ex; 13.04.2015
comment
У меня возникла ошибка при выполнении маршрута с вашим кодом: Ranch listener leptus_http had connection process started with cowboy_protocol:start_link/4 at <0.162.0> 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}]}]} Есть предложения? - person Jean Lebrument; 16.04.2015
comment
Похоже, что leptus использует jiffy для кодирования (github.com/davisp/jiffy). Похоже, что Jiffy ожидает, что эквивалент Erlang JSON будет кортежем из одного элемента, содержащим пролист ({proplist()}). Попробуйте это: {[{[{<<"hello">>, <<"test">>}]}, {[{<<"a">>, <<"b">>}, {<<"c">>, <<"d">>}, {<<"e">>, <<"f">>}, {<<"g">>, <<"h">>}]}]}. - person nu-ex; 16.04.2015
comment
Согласно обсуждению в списке рассылки Erlang, кажется, что кортеж с одним элементом использовался для упрощения сопоставления шаблонов представления Erlang JSON со списком. Вот ссылка на обсуждение: erlang.org/pipermail/erlang- вопросы/2013-июль/074756.html. - person nu-ex; 16.04.2015

Строки Эрланга представляют собой списки целых чисел, поэтому то, что вы возвращаете, это именно то, что вы должны были (ну, на самом деле такие данные могут быть двоичными строками или строками списка). Странная вещь при просмотре ответов в оболочке заключается в том, что оболочка считает подходящим способом форматирования вывода: в виде строки или списка. Если есть какие-либо «управляющие» символы ASCII или значения больше 127, и он не думает, что это локаль UTF-8, тогда он просто напечатает целые числа.

Обычно вы можете быть уверены, что получите персонажей, если сделаете:

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

вместо того, чтобы просто полагаться на оболочку для форматирования вывода в stdio по умолчанию (который всегда возвращается к списку целых чисел, если что-то неясно в среде).

Вставка вашего вывода в мою оболочку...

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
person zxq9    schedule 10.04.2015