ring 2024-05-07

Hi, has anyone managed to implement a custom error page when the user makes a request to a non-existing path?

I am not as familiar with reitit but that is the stacktrace you get if your ring handler returns nil instead of a resp map to the ring jetty adapter

So likely you need to add some kind of catch all route to reitit before turning it into a ring handler there is a #reitit specific channel as well

Ring is a mapping of http requests to clojure functions and does not prescribe routing, there are many routing libraries that people use with ring, and the routing library you use will dictate how you do this.

Compojure is a common routing library and for compojure each route is tried in order, so just put a route at the end that returns a custom 404

Yes, we use reitit But in this case, if the user makes a request to non-existing url, it never reaches reitit. The exception comes from ring/jetty level.

Like this:

java.lang.NullPointerException: Response map is nil
	at ring.util.jakarta.servlet$update_servlet_response.invokeStatic(servlet.clj:91)
	at ring.util.jakarta.servlet$update_servlet_response.invoke(servlet.clj:82)
	at ring.util.jakarta.servlet$update_servlet_response.invokeStatic(servlet.clj:86)
	at ring.util.jakarta.servlet$update_servlet_response.invoke(servlet.clj:82)
	at ring.adapter.jetty$proxy_handler$fn__3281.invoke(jetty.clj:111)
	at ring.adapter.jetty.proxy$org.eclipse.jetty.servlet.ServletHandler$ff19274a.doHandle(Unknown Source)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:221)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1381)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:176)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:484)
	at ring.adapter.jetty.proxy$org.eclipse.jetty.servlet.ServletHandler$ff19274a.doScope(Unknown Source)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:174)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1303)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:129)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122)
	at org.eclipse.jetty.server.Server.handle(Server.java:563)
	at org.eclipse.jetty.server.HttpChannel$RequestDispatchable.dispatch(HttpChannel.java:1598)
	at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:753)
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:501)
	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:287)
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:314)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:100)
	at org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53)
	at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.runTask(AdaptiveExecutionStrategy.java:421)
	at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.consumeTask(AdaptiveExecutionStrategy.java:390)
	at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.tryProduce(AdaptiveExecutionStrategy.java:277)
	at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.run(AdaptiveExecutionStrategy.java:199)
	at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:411)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:969)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob(QueuedThreadPool.java:1194)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1149)
	at java.base/java.lang.Thread.run(Thread.java:830)

I actually added a Ring example recently that uses Reitit and the default handler: https://github.com/ring-clojure/ring-examples/blob/master/hello-world/src/ring/example/hello/server.clj