-
Notifications
You must be signed in to change notification settings - Fork 114
/
exceptions.scala
36 lines (33 loc) · 1.47 KB
/
exceptions.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package unfiltered.netty
import io.netty.buffer.Unpooled
import io.netty.channel.{ ChannelFutureListener, ChannelHandlerContext, ChannelInboundHandler }
import io.netty.channel.ChannelHandler.Sharable
import io.netty.handler.codec.http.{ DefaultFullHttpResponse, HttpVersion, HttpResponseStatus }
import scala.util.control.NonFatal
// note(doug): this type is a little dubious as there as exceptions passed around are no longer wrapped in events. we may wish to remove this
@Sharable
trait ExceptionHandler { self: ChannelInboundHandler =>
def onException(ctx: ChannelHandlerContext, t: Throwable): Unit
override def exceptionCaught(ctx: ChannelHandlerContext,
t: Throwable): Unit = {
onException(ctx, t)
}
}
/** A ChannelInboundHandler mixin that writes a 500 response to clients before closing the channel
* when an exception is thrown */
@Sharable
trait ServerErrorResponse extends ExceptionHandler { self: ChannelInboundHandler =>
def onException(ctx: ChannelHandlerContext, t: Throwable) = {
val ch = ctx.channel
if (ch.isOpen) try {
System.err.println("Exception caught handling request:")
t.printStackTrace()
val res = new DefaultFullHttpResponse(
HttpVersion.HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR, Unpooled.copiedBuffer(
"Internal Server Error".getBytes("utf-8")))
ch.writeAndFlush(res).addListener(ChannelFutureListener.CLOSE)
} catch {
case NonFatal(_) => ch.close()
}
}
}