LINUX.ORG.RU

История изменений

Исправление gh0stwizard, (текущая версия) :

Я так понимаю, что это сделано для совместимости отправки форм методами POST и GET.

Да. Т.к. в POST параметры QUERY_STRING не обязаны присутствовать.

Будет ли разумным соединять $c->req->params и $c->req->data и один хеш (params) если тело запроса JSON?

Без разницы. Для POST QUERY_STRING может быть без параметров, например:

POST http://myapp.org/
Параметров нет. Для GET все параметры передаются в QUERY_STRING. Поскольку в GET-запросы обычно не пихают json-строки, типа:
GET http://myapp.org/?json={"foo":true}
логично выбрать для себя какой-то один вариант (последний вариант тоже работоспособен). Потому что все зависит от движка сервера: ты можешь преобразовывать хоть в xml-деревья из чистого текста.

У каждого подхода есть минусы и плюсы. Когда параметры сериализуются из строки есть вероятность подсунуть искаженную json-строку, которая в итоге приведет к каким-то непредвиденным ошибкам. Также (для перла в особенности) необходимо контролировать максимальный размер входящих данных. JSON::XS может «всасывать» строки размеров в 2Гб. Несколько таких запросов и твой сервер вывалится с ошибкой out of memory (предварительно засвопив всю систему или будучи убитым oom-killer'ом). Но это легко обходится настройкой фронтенда, вроде nginx. В случае сериализации (JSON[::XS] в этом случае вообще не нужен) через HTTP::Body или аналогичный парсер QUERY_STRING, то есть вероятность засорить жесткий диск, ибо данные пишутся сначала туда, а потом от туда читаются. Я пользуюсь вторым вариантом, т.е. дергаю все из params. Но тут есть один ньюнс, сложные структуры вроде хэшы хэшей таким образом строятся особым образом и для этих целей Plack (PSGI) использует модуль Hash::MultiValue (я от него отказался в замен на упрощение API). Что это значит? Это значит, что допустим тебе надо получить нечто такое:

{"tree":{"one":"leaf","two":"leaf"}}
В итоге params (перловый хэш) будет выглядеть наподобии этого:
{
'tree[one]' => 'leaf',
'tree[two]' => 'leaf'
}
И вот тут-то Hash::MultiValue способен разруливать подобные неувязки. Или отказаться от такого и использовать одиночные вложенные массивы:
{"tree":['one','leaf','two','leaf'],"sub":[1,2,3]}
В перле через params они легко «воспримутся» в нормальные структуры.

С каталистом не работал, но думаю там все эти подводные камни уже кем-то решены. В Mojo это решено уже (о чем тебе и сказали выше, вроде вызовается через $req->params->json). А вообще, все это выглядит адскими костылями над непредназначенном для этого HTTP.

Исходная версия gh0stwizard, :

Я так понимаю, что это сделано для совместимости отправки форм методами POST и GET.

Да. Т.к. в POST параметры QUERY_STRING не обязаны присутствовать.

Будет ли разумным соединять $c->req->params и $c->req->data и один хеш (params) если тело запроса JSON?

Без разницы. Для POST QUERY_STRING может быть без параметров, например:

POST http://myapp.org/
Параметров нет. Для GET все параметры передаются в QUERY_STRING. Поскольку в GET-запросы обычно не пихают json-строки, типа:
GET http://myapp.org/?json={"foo":true}
логично выбрать для себя какой-то один вариант (последний вариант тоже работоспособен). Потому что все зависит от движка сервера: ты можешь преобразовывать хоть в xml-деревья из чистого текста.

У каждого подхода есть минусы и плюсы. Когда параметры сериализуются из строки есть вероятность подсунуть искаженную json-строку, которая в итоге приведет к каким-то непредвиденным ошибкам. Также (для перла в особенности) необходимо контролировать максимальный размер входящих данных. JSON::XS может «всасывать» строки размеров в 2Гб. Несколько таких запросов и твой сервер вывалится с ошибкой out of memory (предварительно засвопив всю систему или будучи убитым oom-killer'ом). Но это легко обходится настройкой фронтенда, вроде nginx. В случае сериализации (JSON[::XS] в этом случае вообще не нужен) через HTTP::Body или аналогичный парсер QUERY_STRING, то есть вероятность засорить жесткий диск, ибо данные пишутся сначала туда, а потом от туда читаются. Я пользуюсь вторым вариантом, т.е. дергаю все из params. Но тут есть один ньюнс, сложные структуры вроде хэшы хэшей таким образом строятся особым образом и для этих целей Plack (PSGI) использует модуль Hash::MultiValue (я от него отказался в замен на упрощение API). Что это значит? Это значит, что допустим тебе надо получить нечто такое:

{"tree":{"one":"leaf","two":"leaf"}}
В итоге params (перловый хэш) будет выглядеть наподобии этого:
{
'tree[one]' => 'leaf',
'tree[two]' => 'leaf'
}
И вот тут-то Hash::MultiValue способен разруливать подобные неувязки. Или отказаться от такого и использовать одиночные вложенные массивы:
{"tree":['one','leaf','two','leaf'],"sub":[1,2,3]}
В перле через params они легко «воспримутся» в нормальные структуры.

С каталистом не работал, но думаю там все эти подводные камни уже кем-то решены. А вообще все это выглядит адскими костылями над непредназначенном для этого HTTP.