128128 * <code>prod-like</code> environments:
129129 * </p>
130130 *
131- * <pre>{@code
131+ * <pre>{@code
132132 * {
133133 * on("dev", () -> {
134134 * use(new Whoops());
@@ -155,14 +155,32 @@ public class Whoops implements Jooby.Module {
155155 /** The logging system. */
156156 private final Logger log = LoggerFactory .getLogger (getClass ());
157157
158+ private final int maxFrameSize ;
159+
160+ /**
161+ * Creates a new {@link Whoops} module.
162+ *
163+ * @param maxFrameSize Max number of frame to show in the pretty error page.
164+ */
165+ public Whoops (final int maxFrameSize ) {
166+ this .maxFrameSize = maxFrameSize ;
167+ }
168+
169+ /**
170+ * Creates a new {@link Whoops} module with max frame size of 8.
171+ */
172+ public Whoops () {
173+ this (8 );
174+ }
175+
158176 @ Override
159177 public void configure (final Env env , final Config conf , final Binder binder ) {
160178 boolean whoops = conf .hasPath ("whoops.enabled" )
161179 ? conf .getBoolean ("whoops.enabled" )
162180 : "dev" .equals (env .name ());
163181 if (whoops ) {
164182 ClassLoader loader = env .routes ().getClass ().getClassLoader ();
165- Handler handler = prettyPage (loader , SourceLocator .local (), log );
183+ Handler handler = prettyPage (loader , SourceLocator .local (), maxFrameSize , log );
166184 env .routes ().err (tryPage (handler , log ));
167185 }
168186 }
@@ -174,7 +192,7 @@ static Handler tryPage(final Handler handler, final Logger log) {
174192 }
175193
176194 private static Handler prettyPage (final ClassLoader loader , final SourceLocator locator ,
177- final Logger log ) {
195+ final int maxStackSize , final Logger log ) {
178196 String css = readString (loader , "css/whoops.base.css" );
179197 String clipboard = readString (loader , "js/clipboard.min.js" );
180198 String js = readString (loader , "js/whoops.base.js" );
@@ -234,6 +252,9 @@ private static Handler prettyPage(final ClassLoader loader, final SourceLocator
234252
235253 frames .addAll (frames (loader , locator , head ));
236254
255+ // truncate frames
256+ frames = frames .subList (0 , Math .min (maxStackSize , frames .size ()));
257+
237258 Map <String , Object > context = ImmutableMap .<String , Object > builder ()
238259 .put ("stylesheet" , css )
239260 .put ("zepto" , zepto )
@@ -252,7 +273,7 @@ private static Handler prettyPage(final ClassLoader loader, final SourceLocator
252273
253274 log .error ("execution of: {}{} resulted in exception\n Route:\n {}\n \n Stacktrace:" ,
254275 req .method (), req .path (), req .route ().print (6 ), err );
255- rsp .send (writer .toString ());
276+ rsp .type ( MediaType . html ). send (writer .toString ());
256277 }
257278 };
258279 }
@@ -334,8 +355,9 @@ static String locationOf(final Class clazz) {
334355 }
335356 String cfile = clazz .getName ().replace ("." , "/" ) + ".class" ;
336357 String relativePath = path .replace (cfile , "" );
337- return new File (System .getProperty ("user.dir" )).toPath ()
338- .relativize (Paths .get (relativePath ))
358+ return new File (System .getProperty ("user.dir" ))
359+ .toPath ()
360+ .relativize (Paths .get (relativePath ).toFile ().getCanonicalFile ().toPath ())
339361 .toString ();
340362 }).getOrElse ("~unknown" ))
341363 .orElse ("~unknown" );
0 commit comments