gregspurrier / checked-route

Type-checked Compojure Routes
MIT License
9 stars 0 forks source link

Default error response packager assumes ring/ring-json middleware #1

Open AlexBaranosky opened 11 years ago

AlexBaranosky commented 11 years ago

I'm either doing something wrong, or perhaps checked-routes don't support routes that look like:

(GET "/performance-overview" { ^{:check (partial val/validation-errors schema)} params :params}
   (do :something))

This is the code from my application. The GET++ just handles some common duplication in the code.

(defmacro ^:private GET++ [route environment schema handler]
  `(cr/checked GET ~route { ^{:check (partial val/validation-errors ~schema)} params# :params}
        (~handler ~environment params#)))
(GET++ "/performance-overview" env performance-overview-params-schema web-pages/performance-overview)

When I hit the route, localhost/performance-overview?foo=1, where this route expects no params whatsoever, it seems like the validation errors were evaluated correctly, but something crazy happens inside ring... Notice the errors showing in the stacktrace (#{"Path [:foo] was not specified in the schema."})

Here's my stacktrace:

2012-11-01 10:45:33.614:WARN:oejs.AbstractHttpConnection:/performance-overview?foo=1 java.lang.Exception: Unrecognized body: {:errors {params31auto #{"Path [:foo] was not specified in the schema."}}} at ring.util.servlet$set_body.invoke(servlet.clj:103) at ring.util.servlet$update_servlet_response.invoke(servlet.clj:112) at ring.adapter.jetty$proxy_handler$fn3581.invoke(jetty.clj:21) at ring.adapter.jetty.proxy$org.eclipse.jetty.server.handler.AbstractHandler$0.handle(Unknown Source) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:111) at org.eclipse.jetty.server.Server.handle(Server.java:349) at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:452) at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:884) at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:938) at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:634) at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:230) at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:76) at org.eclipse.jetty.io.nio.SslConnection.handle(SslConnection.java:191) at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:609) at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:45) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:599) at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:534) at java.lang.Thread.run(Thread.java:680)

gregspurrier commented 11 years ago

This is because the default error response packager assumes that you are using the ring/ring-json wrapper that converts map response bodies to JSON. You can work around this by re-binding checked-route.core/*make-error-response* to something that will generate a string for the response :body field.

gregspurrier commented 11 years ago

I will update the default *make-error-response* function to return a conforming Ring response so that it does not depend on any middleware.

AlexBaranosky commented 11 years ago

Where can I find that middleware?

gregspurrier commented 11 years ago

It's: https://github.com/ring-clojure/ring-json / https://clojars.org/ring/ring-json

wrap-json-response is the middleware that you need to insert into your stack.

AlexBaranosky commented 11 years ago

Nice. That worked. Here's what I see in the browser now, which uses my custome ErrorReporter:

{"errors":{"params3714auto__":[{"type":"extraneous-path","unexpected-path":["foo"]}]}}