pedestal 2024-07-03

Hey congrats on the 0.7.0 release! I am giving upgrading to 0.7.0 a whirl for cljdoc. I am happy to see that broken pipe exceptions are now ignored by default. We had a hack in cljdoc to deal with this which I should now be able to remove!

Thanks! We also adopted this fix in a custom :exception-analyzer.

👍 1

Ah. I wonder if the default broken pipe check is a bit off? Current https://github.com/pedestal/pedestal/blob/88e052a1230bf49453d0a953d5260d2e3d6101a1/service/src/io/pedestal/http/impl/servlet_interceptor.clj#L261-L265:

(defn- is-broken-pipe?
  "Checks for a broken pipe exception, which (by default) is omitted."
  [exception]
  (and (instance? IOException exception)
       (.equalsIgnoreCase "broken pipe" (ex-message exception))))
But for cljdoc our hack checked the root cause instead of the main exception. Thanks to your great doc updates, I easily replaced the default :exception-analyzer with one that calls an is-broken-pipe? implemented like so:
(defn- is-broken-pipe? [exception]
   (let [cause (stacktrace/root-cause exception)]
     (and (instance? IOException cause)
          (= "Broken pipe" (ex-message cause)))))

It’s not impossible that there’s a bug there. I’ll look into the tests.

♥️ 1

For anyone interested, https://github.com/cljdoc/cljdoc/pull/891. Easy peasy lemon squeezy!

2

how would I reject a request to open a websocket connection in 0.7.0? if possible i'd rather reject the http request rather than close the ws immediately after its opened

Currently, websocket requests don't flow through the normal pipelines. I think that's something that should be addressed in 0.7.x or 0.8.0 ... that is, set up an (optional) interceptor pipeline with a terminator that upgrades the request to a WS connection

I see this as an optional :interceptors key in the websocket map, alongside :on-open, etc.

i understand, thanks for the response!

I think this depends on the servlet in use. If you are using Jetty, the following comment may provide some guidance https://github.com/lynaghk/jetty7-websockets-async/issues/5#issuecomment-30884417

i'm not sure i understand that... i'm using the new key ::http/websockets in the service map like...

{::http/routes #{["/" :get `root-handler]}
 ::http/type :jetty
 ::http/host "0.0.0.0"
 ::http/port port
 ::http/websockets
 {"/ws"
  {:on-open  on-open
   :on-text  on-text
   :on-close on-close
   :on-error on-error}}}
i'm not sure how, using this service map key, to reject a websocket request before it is upgraded. previously i would use the ::http/container-options with
{:context-configurator
 (fn [context]
   (ws/add-ws-endpoints
    context
    {"/ws" actions}
    {:listener-fn create-listener}))}
and reject the response in create-listener