Compojure: получение тела из запроса POST, из которого отсутствовал заголовок Content-Type - PullRequest
4 голосов
/ 21 ноября 2011

Учитывая этот фрагмент:

(defroutes main-routes
    (POST "/input/:controller" request
        (let [buff (ByteArrayOutputStream.)]
            (copy (request :body) buff) 
            ;; --- snip

Значение buff будет непустым байтовым массивом, если в запросе есть заголовок Content-Type.Значение может быть несущественным, заголовок просто должен быть там.

Однако мне нужно вывести тело (хм ..., которое вышло неправильно), если запрос пришел без типа контента, так чтоклиент может отследить ошибочную загрузку.(Программное обеспечение для загрузки не находится под моим контролем, и его сопровождающие не будут предоставлять ничего дополнительного в заголовках.)

Спасибо за любые идеи о том, как решить эту проблему или обойти ее! * РЕДАКТИРОВАТЬ

*:

Вот заголовки, которые я получаю от клиента:

{
   "content-length" "159",
   "accept" "*/*",
   "host" (snip),
   "user-agent" (snip)
}

Кроме того, я обнаружил, что Ring, используя экземпляр ServletRequest Java, заполняет тип контента стандартным значением по умолчанию,х-WWW-форм-urlencoded.Теперь я предполагаю, что HTTPParser, который предоставляет тело через HTTPParser # Input, не может правильно его проанализировать.

Ответы [ 2 ]

1 голос
/ 23 мая 2012

У меня такая же проблема. Это определенно одно из промежуточного программного обеспечения, которое не может правильно проанализировать тело и преобразовать :body. Основная проблема заключается в том, что Content-Type предполагает, что тело должно быть разборчивым.

Используя ngrep, я выяснил, как curl путает промежуточное ПО. Следующее, хотя интуитивно (или довольно сексуально) в командной строке отправляет неверный Content-Type, который сбивает с толку промежуточное ПО:

curl -nd "Unknown error" http://localhost:3000/event/error                                                                            

T 127.0.0.1:44440 -> 127.0.0.1:3000 [AP]
POST /event/error HTTP/1.1.
Authorization: Basic SzM5Mjg6ODc2NXJkZmdoam5idmNkOQ==.
User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3.
Host: localhost:3000.
Accept: */*.
Content-Length: 13.
Content-Type: application/x-www-form-urlencoded.
.
Unknown error

Однако следующее вынуждает Content-Type быть непрозрачным, и промежуточное ПО не будет мешать :body.

curl -nd "Unknown error" -H "Content-Type: application/data" http://localhost:3000/event/error                                        

T 127.0.0.1:44441 -> 127.0.0.1:3000 [AP]
POST /event/error HTTP/1.1.
Authorization: Basic SzM5Mjg6ODc2NXJkZmdoam5idmNkOQ==.
User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3.
Host: localhost:3000.
Accept: */*.
Content-Type: application/data.
Content-Length: 13.
.
Unknown error

Я подумываю о замене промежуточного программного обеспечения на более либеральное, потому что, хотя запрос неверен, я все же хотел бы решить, что делать с телом самостоятельно. Это действительно странный выбор - ноль тела запроса, когда запрос не имеет смысла. Я на самом деле думаю, что более правильным было бы передать его обработчику ошибок, который по умолчанию будет возвращать 400 Bad Request или 406 Not Acceptable.

Есть мысли по этому поводу? В моем случае я мог бы предложить патч для Compojure.

1 голос
/ 21 ноября 2011

Согласно:

http://mmcgrana.github.com/ring/ring.middleware.content-type-api.html

тип контента по умолчанию: application/octet-stream. Если вы активно не поддерживаете этот тип контента, разве вы не можете просто проверить, соответствует ли тип контента этому, а затем сбросить все, что вам нужно, основываясь на этом?

...