3

I have a web service in Compojure with one route that looks like this:

 "/myapp/dosomething/:input"

This works well when :input is something normal for the app to handle, such as a word, a string of digits etc, but when garbage is put in, such as

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

I get a 500 error. My question is, how to I trap this, and return 400 instead?

 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)
David Williams
  • 8,388
  • 23
  • 83
  • 171
  • 2
    I'm trying to reproduce the error but I'm not getting a 500 with that URL. Just to make sure I'm directly calling the `clout.core/path_decode`. This is what I'm evaluating `(path-decode "/myapp/dosomething/%25%24%25%5E%24%25%5E%25%24%5E")`, and this is the return value `"/myapp/dosomething/%$%^$%^%$^"`. – juan.facorro Jun 28 '13 at 21:02
  • 1
    @juan Considering that error is about %$ being illegal escape sequence, it seems like url is already unescaped before fed to url parser – Slartibartfast Jun 28 '13 at 21:05
  • 1
    @Slartibartfast I thought so too, the thing is I'm getting a `400 Bad Request` (not a 500) error if I try the following URL "/myapp/dosomething/%$%^$%^%$^". Maybe it's just that we have different setups since I'm actually running the ring app in the REPL. I just want to make sure we can address the same issue. – juan.facorro Jun 28 '13 at 21:12
  • Hi guys, thanks for taking a look! About the setup, this is deployed as an uberwar in a jetty container. – David Williams Jun 28 '13 at 22:44
  • @juan.facorro, do you know how to trap the bad path decoding? – David Williams Jun 28 '13 at 23:40
  • @DavidWilliams Did you actually manage to solve this? We have the same problem in production using ring-jetty-adapter and Jetty 8.1.14.v20131031. – joelittlejohn Nov 28 '13 at 13:56
  • Hi @Joe, yes, weavejester's solution below took care of it. I would upgrade all versions to latest. – David Williams Nov 29 '13 at 21:36

1 Answers1

4

This issue occurs in war files generated by the Lein-Ring plugin, and has been recently fixed in Lein-Ring 0.8.6 as a result of this report.

The cause has to do with the difference in how Java Servlets and Ring deal with the path-info field. The Java Servlet specification has the context path url-encoded, but the path info is decoded. Ring treats both the :context and :path-info keys as url-encoded.

weavejester
  • 575
  • 3
  • 3