ring

lucian303 2017-11-15T22:11:55.000084Z

i'm trying to set up ring middleware to log all exceptions, but i can't seem to trigger the catch block in my middleware handler. any ideas?

(defn wrap-exception-handler [handler]
  (fn [request]
    (try (handler request)
         (catch Exception e
           (println "logged error")
           (timbre/error e)
           {:status 500 :body "An error occurred"}))))

2017-11-15T22:40:07.000204Z

@lucian303 I have a wrapper to handle exceptions just like yours in my current project and it works. But there's one thing that it's worth looking into, the thing trowing inherits from Error or Exception? there's a difference in those two types of errors in Java and the ones inheriting from Error will not be caught in a catch for Exception

lucian303 2017-11-15T22:44:00.000114Z

@zignd i have defined a route with the below throw statement for testing. it's just a regular Exception ... i also tried modifying the handler to take a Throwable, but it won't catch the exception:

(throw (Exception. "An error has occurred"))

2017-11-15T22:45:35.000163Z

@lucian303 in this case I'd check the order in which you're registering your wrappers, can you post it?

lucian303 2017-11-15T22:49:17.000056Z

sure. i've tried it as both the first and last handlers in the chain below. also without the wrap-defaults:

(defn wrap-base [handler]
  (-> ((:middleware defaults) handler)
      (wrap-sentry (environ/env :sentry-url) ["api-proxy"])
      (wrap-defaults
        (-> api-defaults
            (assoc-in [:security :anti-forgery] false)
            (dissoc :session)))
      wrap-exception-handler))

2017-11-15T23:02:15.000325Z

i'm kind of confused here, i'm still kind of beginner, but

(-> api-defaults
            (assoc-in [:security :anti-forgery] false)
            (dissoc :session))
works as expected? because api-defaults from ring.middleware.defaults doesn't seem to have :session key. but still, i don't think this would be the issue

lucian303 2017-11-15T23:14:41.000245Z

you're right about that. that was left over from when the app was using site-defaults i've changed that call to simply (wrap-defaults api-defaults)

lucian303 2017-11-15T23:15:07.000016Z

but yeah, it's not the issue

2017-11-15T23:16:39.000151Z

i wonder if it even gets called:

(defn wrap-exception-handler [handler]
  (fn [request]
    (println "called") ; <----- here
    (try (handler request)
         (catch Exception e
           (println "logged error")
           (timbre/error e)
           {:status 500 :body "An error occurred"}))))

2017-11-15T23:17:45.000129Z

@lucian303 do your request reaches that point i indicated in the snippet above?

2017-11-15T23:18:53.000185Z

cause, maybe it's not a problem with the error handling, but something related to the other wrappers

2017-11-15T23:19:34.000044Z

@lucian303 does the sentry wrapper attempts to catch exceptions?

lucian303 2017-11-15T23:30:31.000158Z

@zignd yes, the handler is called, it's just that the exception is never caught. the sentry handler does catch exceptions but rethrows them. i've actually removed the other handlers including wrap-defaults but it still won't catch exceptions

lucian303 2017-11-15T23:37:54.000434Z

the wrap-sentry handler seems to actually be very similar to mine, but it is also not working (which is why i'm trying to write my own). very strange ...

(defn wrap-sentry [handler dsn & [opts]]
  (fn [req]
    (let [alter-fn (or (:http-alter-fn opts)
                       identity)]
      (try
        (handler req)
        (catch Exception e
          (capture-error dsn req e (:extra opts) (:namespaces opts) alter-fn)
          (throw e))
        (catch AssertionError e
          (capture-error dsn req e (:extra opts) (:namespaces opts) alter-fn)
          (throw e))))))

2017-11-15T23:54:51.000307Z

that's weird, my last bet would be on the handler returned from this call ((:middleware defaults) handler), maybe there's something in it worth investigating