Compojure: Trap 500 Ошибка декодирования URL

У меня есть веб-сервис в Compojure с одним маршрутом, который выглядит так:

 "/myapp/dosomething/:input"

Это хорошо работает, когда :input является чем-то обычным для обработки приложением, например, словом, строкой цифр и т. д., но когда вводится мусор, например

GET /myapp/dosomething/%25%24%25%5E%24%25%5E%25%24%5E

Я получаю ошибку 500. Мой вопрос в том, как мне поймать это и вместо этого вернуть 400?

 HTTP ERROR 500

 Problem accessing /myapp/dosomething/%25%24%25%5E%24%25%5E%25%24%5E. Reason:

     Server Error
 Caused by:

 java.lang.IllegalArgumentException: URLDecoder: Illegal hex characters in escape (%) pattern - For input string: "$%"
at java.net.URLDecoder.decode(URLDecoder.java:192)
at clout.core$path_decode.invoke(core.clj:33)
at clout.core$path_decode.invoke(core.clj:31)
at clojure.core$map$fn__4207.invoke(core.clj:2485)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
at clojure.lang.LazySeq.seq(LazySeq.java:60)
at clojure.lang.RT.seq(RT.java:484)
at clojure.core$seq.invoke(core.clj:133)
at clojure.core$map$fn__4211.invoke(core.clj:2490)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
at clojure.lang.LazySeq.seq(LazySeq.java:60)
at clojure.lang.RT.seq(RT.java:484)
at clojure.core$seq.invoke(core.clj:133)
at clojure.core.protocols$seq_reduce.invoke(protocols.clj:30)
at clojure.core.protocols$fn__6026.invoke(protocols.clj:54)
at clojure.core.protocols$fn__5979$G__5974__5992.invoke(protocols.clj:13)
at clojure.core$reduce.invoke(core.clj:6177)
at clout.core$assoc_keys_with_groups.invoke(core.clj:54)
at clout.core.CompiledRoute.route_matches(core.clj:84)
at compojure.core$if_route$fn__472.invoke(core.clj:38)
at compojure.core$if_method$fn__465.invoke(core.clj:24)
at compojure.core$routing$fn__490.invoke(core.clj:106)
at clojure.core$some.invoke(core.clj:2443)
at compojure.core$routing.doInvoke(core.clj:106)
at clojure.lang.RestFn.applyTo(RestFn.java:139)
at clojure.core$apply.invoke(core.clj:619)
at compojure.core$routes$fn__494.invoke(core.clj:111)
at ring.middleware.keyword_params$wrap_keyword_params$fn__710.invoke(keyword_params.clj:27)
at ring.middleware.nested_params$wrap_nested_params$fn__749.invoke(nested_params.clj:65)
at ring.middleware.params$wrap_params$fn__682.invoke(params.clj:55)
at ring.middleware.multipart_params$wrap_multipart_params$fn__777.invoke(multipart_params.clj:103)
at ring.middleware.flash$wrap_flash$fn__1064.invoke(flash.clj:14)
at ring.middleware.session$wrap_session$fn__1055.invoke(session.clj:40)
at ring.middleware.cookies$wrap_cookies$fn__986.invoke(cookies.clj:160)
at vinws_chrome.servlet$_service$fn__116.invoke(servlet.clj:1)
at ring.util.servlet$make_service_method$fn__54.invoke(servlet.clj:145)

person David Williams    schedule 28.06.2013    source источник
comment
Я пытаюсь воспроизвести ошибку, но не получаю 500 с этим URL. Просто чтобы убедиться, что я напрямую вызываю clout.core/path_decode. Это то, что я оцениваю (path-decode "/myapp/dosomething/%25%24%25%5E%24%25%5E%25%24%5E"), и это возвращаемое значение "/myapp/dosomething/%$%^$%^%$^".   -  person juan.facorro    schedule 29.06.2013
comment
@juan Учитывая, что ошибка связана с тем, что %$ является недопустимой escape-последовательностью, кажется, что URL-адрес уже не экранирован, прежде чем он будет передан парсеру URL-адресов.   -  person Slartibartfast    schedule 29.06.2013
comment
@Slartibartfast Я тоже так думал, дело в том, что я получаю ошибку 400 Bad Request (не 500), если пытаюсь использовать следующий URL-адрес /myapp/dosomething/%$%^$%^%$^. Может быть, дело в том, что у нас разные настройки, так как я на самом деле запускаю кольцевое приложение в REPL. Я просто хочу убедиться, что мы можем решить одну и ту же проблему.   -  person juan.facorro    schedule 29.06.2013
comment
Привет, ребята, спасибо, что заглянули! Что касается установки, это развернуто как uberwar в контейнере пристани.   -  person David Williams    schedule 29.06.2013
comment
@juan.facorro, вы знаете, как отловить декодирование неправильного пути?   -  person David Williams    schedule 29.06.2013
comment
@DavidWilliams Вам действительно удалось это решить? У нас такая же проблема в продакшене с использованием ring-jetty-adapter и Jetty 8.1.14.v20131031.   -  person joelittlejohn    schedule 28.11.2013
comment
Привет, @Joe, да, решение weavejester, приведенное ниже, позаботилось об этом. Я бы обновил все версии до последних.   -  person David Williams    schedule 30.11.2013


Ответы (1)


Эта проблема возникает в военных файлах, созданных подключаемым модулем Lein-Ring, и была недавно исправлена ​​в Lein-Ring 0.8.6 в результате этого отчета.

Причина связана с различием в том, как сервлеты Java и Ring обрабатывают поле информации о пути. Спецификация сервлета Java имеет закодированный URL-адрес пути контекста, но информация о пути декодируется. Ring обрабатывает ключи :context и :path-info как закодированные в URL.

person weavejester    schedule 03.07.2013