Packages
plug
1.3.6
1.20.3
1.20.2
1.20.1
retired
1.20.0
retired
1.19.5
1.19.4
1.19.3
1.19.2
1.19.1
1.19.0
1.18.5
1.18.4
1.18.3
1.18.2
1.18.1
1.18.0
1.17.4
1.17.3
1.17.2
1.17.1
1.17.0
1.16.6
1.16.5
1.16.4
1.16.3
1.16.2
1.16.1
1.16.0
1.15.6
1.15.5
1.15.4
1.15.3
1.15.2
1.15.1
1.15.0
1.14.2
1.14.1
1.14.0
1.13.6
1.13.5
1.13.4
1.13.3
1.13.2
1.13.1
retired
1.13.0
retired
1.12.1
1.12.0
1.11.1
1.11.0
1.10.4
1.10.3
1.10.2
1.10.1
1.10.0
1.9.0
1.8.3
1.8.2
1.8.1
1.8.0
1.7.2
1.7.1
1.7.0
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.5.1
1.5.0
1.5.0-rc.2
1.5.0-rc.1
1.5.0-rc.0
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.4.0-rc.0
1.3.6
1.3.5
1.3.4
1.3.3
1.3.2
1.3.1
1.3.0
1.2.6
1.2.5
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.2.0-rc.0
1.1.9
1.1.8
1.1.7
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.14.0
0.13.1
0.13.0
0.12.2
0.12.1
0.12.0
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.0
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.0
0.6.0
0.5.3
0.5.2
0.5.1
0.5.0
0.4.4
0.4.3
0.4.2
0.4.1
Compose web applications with functions
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/plug/templates/debugger.html.eex
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title><%= h @title %> at <%= h method(@conn) %> <%= h @conn.request_path %></title>
<meta name="viewport" content="width=device-width">
<style>/*! normalize.css v4.2.0 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block}audio:not([controls]){display:none;height:0}progress{vertical-align:baseline}template,[hidden]{display:none}a{background-color:transparent;-webkit-text-decoration-skip:objects}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:inherit}b,strong{font-weight:bolder}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}svg:not(:root){overflow:hidden}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}figure{margin:1em 40px}hr{box-sizing:content-box;height:0;overflow:visible}button,input,optgroup,select,textarea{font:inherit;margin:0}optgroup{font-weight:bold}button,input{overflow:visible}button,select{text-transform:none}button,html [type="button"],[type="reset"],[type="submit"]{-webkit-appearance:button}button::-moz-focus-inner,[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring{outline:1px dotted ButtonText}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-cancel-button,[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-input-placeholder{color:inherit;opacity:0.54}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}</style>
<style>
html, body, td, input {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
}
* {
box-sizing: border-box;
}
html {
font-size: 15px;
line-height: 1.6;
background: #fff;
color: <%= @style.text_color %>;
}
@media (max-width: 768px) {
html {
font-size: 14px;
}
}
@media (max-width: 480px) {
html {
font-size: 13px;
}
}
button:focus,
summary:focus {
outline: 0;
}
summary {
cursor: pointer;
}
pre {
font-family: <%= @style.monospace_font %>;
overflow: auto;
max-width: 100%;
}
.top-details {
padding: 48px;
background: #f9f9fa;
}
.top-details,
.conn-info {
padding: 48px;
}
@media (max-width: 768px) {
.top-details,
.conn-info {
padding: 32px;
}
}
@media (max-width: 480px) {
.top-details,
.conn-info {
padding: 16px;
}
}
/*
* Exception logo
*/
<%= if @style.logo do %>
.exception-logo {
position: absolute;
right: 48px;
top: 48px;
pointer-events: none;
width: 100%;
}
.exception-logo:before {
content: '';
display: block;
height: 64px;
width: 100%;
background-size: auto 100%;
background-image: url("<%= @style.logo %>");
background-position: right 0;
background-repeat: no-repeat;
margin-bottom: 16px;
}
@media (max-width: 768px) {
.exception-logo {
position: static;
}
.exception-logo:before {
height: 32px;
background-position: left 0;
}
}
@media (max-width: 480px) {
.exception-logo {
display: none;
}
}
<% end %>
/*
* Exception info
*/
/* Compensate for logo placement */
@media (min-width: 769px) {
.exception-info {
max-width: 90%;
}
}
.exception-info > .struct,
.exception-info > .title,
.exception-info > .detail {
margin: 0;
padding: 0;
}
.exception-info > .struct {
font-size: 1em;
font-weight: 700;
color: <%= @style.primary %>;
}
.exception-info > .struct > small {
font-size: 1em;
color: <%= @style.accent %>;
font-weight: 400;
}
/* Hide path until hover */
.exception-info > .struct > .path {
opacity: 0;
-webkit-transition: opacity 100ms linear;
transition: opacity 100ms linear;
}
.exception-info:hover > .struct > .path {
opacity: 1;
}
.exception-info > .title {
font-size: <%= :math.pow(1.2, 4) %>em;
line-height: 1.4;
font-weight: 300;
color: <%= @style.primary %>;
}
@media (max-width: 768px) {
.exception-info > .title {
font-size: <%= :math.pow(1.15, 4) %>em;
}
}
@media (max-width: 480px) {
.exception-info > .title {
font-size: <%= :math.pow(1.1, 4) %>em;
}
}
.exception-info > .detail {
margin-top: 1.3em;
white-space: pre;
}
/*
* Code explorer
*/
.code-explorer {
margin: 32px 0 0 0;
}
@media (max-width: 768px) {
.code-explorer {
margin-top: 16px;
}
}
.code-explorer:after {
content: '';
display: table;
clear: both;
zoom: 1;
}
.code-explorer > .code-snippets {
float: left;
width: 45%;
}
.code-explorer > .stack-trace {
float: right;
width: 55%;
padding-left: 32px;
}
/* Collapse to single-column */
@media (max-width: 960px) {
.code-explorer > .code-snippets {
float: none;
width: auto;
margin-bottom: 16px;
}
.code-explorer > .stack-trace {
float: none;
width: auto;
padding-left: 0;
}
}
/*
* Snippets
*/
.code-snippets {
}
/*
* Frame info:
* Holds the code (code-block) and more
*/
.frame-info {
background: white;
box-shadow:
0 1px 3px rgba(80, 100, 140, .1),
0 8px 15px rgba(80, 100, 140, .05);
}
.frame-info > .meta,
.frame-info > .file {
padding: 12px 16px;
white-space: no-wrap;
font-size: <%= :math.pow(1.2, -1) %>em;
}
@media (max-width: 480px) {
.frame-info > .meta,
.frame-info > .file {
padding: 6px 16px;
font-size: <%= :math.pow(1.1, -1) %>em;
}
}
.frame-info > .file > a {
text-decoration: none;
color: <%= @style.text_color %>;
font-weight: 700;
}
.frame-info > .code {
border-top: solid 1px <%= @style.line_color %>;
border-bottom: solid 1px <%= @style.line_color %>;
}
/* Hiding */
.frame-info {
display: none;
}
.frame-info.-active {
display: block;
}
.frame-info > details.meta {
padding: 0;
}
.frame-info > details.meta > summary {
padding: 12px 16px;
}
/*
* Frame details
*/
.frame-summary.-short {
color: <%= @style.accent %>;
}
.frame-summary > .app {
color: <%= @style.primary %>;
font-weight: 700;
}
.frame-summary > .app:after {
content: 'ยท';
margin: 0 .2em;
}
/*
* Code block:
* The `pre` that holds the code
*/
.code-block {
margin: 0;
padding: 12px 0;
font-size: .8em;
line-height: 1.4;
white-space: normal;
}
.code-block > .line {
white-space: pre;
display: block;
padding: 0 16px;
}
/* Line highlight */
.code-block > .line.-highlight {
background-color: <%= @style.highlight %>;
-webkit-animation: line-highlight 750ms linear;
animation: line-highlight 750ms linear;
}
@-webkit-keyframes line-highlight {
0% { background-color: <%= @style.highlight %>; }
25% { background-color: <%= @style.red_highlight %>; }
50% { background-color: <%= @style.highlight %>; }
75% { background-color: <%= @style.red_highlight %>; }
}
@keyframes line-highlight {
0% { background-color: <%= @style.highlight %>; }
25% { background-color: <%= @style.red_highlight %>; }
50% { background-color: <%= @style.highlight %>; }
75% { background-color: <%= @style.red_highlight %>; }
}
.code-block > .line > .ln {
color: <%= @style.accent %>;
margin-right: 1.5em;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.code-block > .line > .code {
font-family: <%= @style.monospace_font %>;
}
/*
* Empty code
*/
.code-block-empty {
text-align: center;
color: <%= @style.accent %>;
padding-top: 48px;
padding-bottom: 48px;
}
/*
* Stack trace heading
*/
.stack-trace-heading {
padding-top: 8px;
}
.stack-trace-heading:after {
content: '';
display: block;
clear: both;
zoom: 1;
border-bottom: solid 1px <%= @style.line_color %>;
padding-top: 12px;
margin-bottom: 16px;
}
.stack-trace-heading > h3 {
display: none;
}
.stack-trace-heading > label {
display: block;
padding-left: 8px;
line-height: 1.9;
font-size: <%= :math.pow(1.2, -1) %>em;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.stack-trace-heading > label > input {
margin-right: .3em;
}
@media (max-width: 480px) {
.stack-trace-heading > label {
font-size: <%= :math.pow(1.1, -1) %>em;
}
}
/*
* Stack trace
*/
.stack-trace-list,
.stack-trace-list > li {
margin: 0;
padding: 0;
list-style-type: none;
}
.stack-trace-list > li > .stack-trace-item.-all {
display: none;
}
.stack-trace-list.-show-all > li > .stack-trace-item.-all {
display: block;
}
/*
* Stack trace item:
* The clickable line to inspect a stack trace
*/
.stack-trace-item {
font-size: <%= :math.pow(1.2, -1) %>em;
display: block;
width: 100%;
border: 0;
margin: 0;
padding: 4px 8px;
background: transparent;
cursor: pointer;
text-align: left;
overflow: hidden;
white-space: nowrap;
}
.stack-trace-item:hover,
.stack-trace-item:focus {
background-color: rgba(80, 100, 140, 0.05);
}
.stack-trace-item,
.stack-trace-item:active {
color: <%= @style.text_color %>;
}
.stack-trace-item:active {
background-color: rgba(80, 100, 140, 0.1);
}
.stack-trace-item.-active {
background-color: white;
}
/* Circle */
.stack-trace-item > .left:before {
content: '';
display: inline-block;
width: 8px;
height: 8px;
background: <%= @style.accent %>;
border-radius: 50%;
margin-right: 8px;
}
.stack-trace-item.-app > .left:before {
background: <%= @style.primary %>;
opacity: 1;
}
.stack-trace-item.-app > .left > .app {
display: none;
}
.stack-trace-item > .left {
float: left;
max-width: 55%;
}
.stack-trace-item > .info {
color: <%= @style.gray %>;
float: right;
max-width: 45%;
}
.stack-trace-item > .left,
.stack-trace-item > .info {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.stack-trace-item > .left > .filename > .line {
color: <%= @style.accent %>;
}
/* App name */
.stack-trace-item > .left > .app {
color: <%= @style.accent %>;
}
.stack-trace-item > .left > .app:after {
content: 'ยท';
margin: 0 .2em;
}
/*
* Code as a blockquote:
* Like `pre` but with wrapping
*/
.code-quote {
font-family: <%= @style.monospace_font %>;
font-size: <%= :math.pow(1.2, -1) %>em;
margin: 0;
overflow: auto;
max-width: 100%;
word-wrap: break-word;
white-space: normal;
}
.code-quote.-padded {
padding: 0 16px 16px 16px;
}
/*
* Conn info
*/
.conn-info {
border-top: solid 1px <%= @style.line_color %>;
}
/*
* Conn details
*/
.conn-details {
}
.conn-details + .conn-details {
margin-top: 16px;
}
.conn-details > summary {
}
.conn-details > dl {
display: block;
overflow: hidden;
margin: 0;
padding: 4px 0;
border-bottom: solid 1px <%= @style.line_color %>;
white-space: nowrap;
text-overflow: ellipsis;
}
.conn-details > dl:first-of-type {
margin-top: 16px;
border-top: solid 1px <%= @style.line_color %>;
}
/* Term */
.conn-details > dl > dt {
width: 20%;
float: left;
font-size: <%= :math.pow(1.2, -1) %>em;
color: <%= @style.gray %>;
overflow: hidden;
text-overflow: ellipsis;
position: relative;
top: -1px; /* Compensate for font metrics */
}
/* Definition */
.conn-details > dl > dd {
width: 80%;
float: left;
}
@media (max-width: 480px) {
.conn-details > dl > dt {
font-size: <%= :math.pow(1.1, -1) %>em;
}
}
</style>
</head>
<body>
<div class="top-details">
<%= if @style.logo do %>
<aside class="exception-logo"></aside>
<% end %>
<header class="exception-info">
<% [headline | details] = String.split(@message, "\n\n") %>
<h5 class="struct">
<%= h @title %>
<small>at <%= h method(@conn) %></small>
<small class="path"><%= h @conn.request_path %></small>
</h5>
<h1 class="title"><%= h headline %></h1>
<%= for detail <- details do %>
<p class="detail"><%= h detail %></p>
<% end %>
</header>
<div class="code-explorer">
<div class="code-snippets">
<%= for frame <- @frames do %>
<div class="frame-info" data-index="<%= frame.index %>" role="stack-trace-details">
<div class="file">
<a href="<%= frame.link %>"><%= h frame.file %></a>
</div>
<%= if (snippet = frame.snippet) && snippet != [] do %>
<pre class="code code-block"><%= for {index, line, highlight} <- snippet do %><span class="line <%= if highlight, do: "-highlight" %>"><span class="ln"><%= h index %></span><span class="code"><%= h String.rstrip(line) %></span></span>
<% end %></pre>
<% else %>
<div class="code code-block-empty">No code available.</div>
<% end %>
<%= if frame.args != [] do %>
<details class="meta">
<summary class="frame-summary">
<%= if app = frame.app do %>
<span class="app"><%= h app %></span>
<% end %>
<%= h frame.info %>
</summary>
<blockquote class="code-quote -padded"><%= h inspect(frame.args) %></blockquote>
</details>
<% else %>
<div class="meta">
<div class="frame-summary -short">
<%= if app = frame.app do %>
<span class="app"><%= h app %></span>
<% end %>
<%= h frame.info %>
</div>
</div>
<% end %>
</div>
<% end %>
</div>
<div class="stack-trace">
<div class="stack-trace-heading">
<label><input type="checkbox" role="show-all-toggle"> Show all frames</label>
</div>
<ul class="stack-trace-list" role="stack-trace-list">
<%= for frame <- @frames do %>
<li>
<button class="stack-trace-item -<%= frame.context %>" role="stack-trace-item" data-index="<%= frame.index %>">
<span class="left">
<%= if app = frame.app do %>
<span class="app"><%= h app %></span>
<% end %>
<span class="filename">
<%= h frame.file %><%= if frame.line do %><span class="line">:<%= h frame.line %></span><% end %>
</span>
</span>
<span class="info"><%= h frame.info %></span>
</button>
</li>
<% end %>
</ul>
</div>
</div>
</div>
<div class="conn-info">
<%= if @params && @params != %{} do %>
<details class="conn-details" open>
<summary>Params</summary>
<%= for {key, value} <- @params do %>
<dl>
<dt><%= h key %></dt>
<dd><pre><%= h inspect(value) %></pre></dd>
</dl>
<% end %>
</details>
<% end %>
<details class="conn-details">
<summary>Request info</summary>
<dl>
<dt>URI:</dt>
<dd class="code-quote"><%= h url(@conn) %></dd>
</dl>
<dl>
<dt>Query string:</dt>
<dd class="code-quote"><%= h @conn.query_string %></dd>
</dl>
<dl>
<dt>Peer:</dt>
<dd class="code-quote"><%= h peer(@conn) %></dd>
</dl>
</details>
<details class="conn-details">
<summary>Headers</summary>
<%= for {key, value} <- Enum.sort(@conn.req_headers) do %>
<dl>
<dt><%= h key %></dt>
<dd class="code-quote"><%= h value %></dd>
</dl>
<% end %>
</details>
<%= if @session && @session != %{} do %>
<details class="conn-details">
<summary>Session</summary>
<%= for {key, value} <- @session do %>
<dl>
<dt><%= h key %></dt>
<dd><pre><%= h inspect(value) %></pre></dd>
</dl>
<% end %>
</details>
<% end %>
</div>
<script>(function () {
var $items = document.querySelectorAll('[role~="stack-trace-item"]')
var $toggle = document.querySelector('[role~="show-all-toggle"]')
var $list = document.querySelector('[role~="stack-trace-list"]')
each($items, function ($item) {
on($item, 'click', itemOnclick)
})
on($toggle, 'click', toggleOnclick)
// Auto-check "show all" if there are no app frames.
if (document.querySelectorAll('[role~="stack-trace-list"] .-app').length === 0) {
$toggle.checked = true
toggleOnclick.call($toggle)
}
function toggleOnclick () {
if (this.checked) {
addClass($list, '-show-all')
} else {
removeClass($list, '-show-all')
}
}
function itemOnclick () {
var idx = this.getAttribute('data-index')
var $detail = document.querySelector('[role~="stack-trace-details"].-active')
if ($detail) removeClass($detail, '-active')
$detail = document.querySelector('[role~="stack-trace-details"][data-index="' + idx + '"]')
if ($detail) addClass($detail, '-active')
var $item = document.querySelector('[role~="stack-trace-item"].-active')
if ($item) removeClass($item, '-active')
$item = document.querySelector('[role~="stack-trace-item"][data-index="' + idx + '"]')
if ($item) addClass($item, '-active')
}
var $first =
document.querySelector('[role~="stack-trace-item"].-app:first-of-type') ||
document.querySelector('[role~="stack-trace-item"]:first-of-type')
if ($first) itemOnclick.call($first)
/*
* Helpers
*/
function each (list, fn) {
for (var i = 0, len = list.length; i < len; i++) {
var item = list[i]
fn(item)
}
}
function addClass (el, className) {
if (el.classList) {
el.classList.add(className)
} else {
el.className += ' ' + className
}
}
function removeClass (el, className) {
if (el.classList) {
el.classList.remove(className)
} else {
var expr = new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi')
el.className = el.className.replace(expr, ' ')
}
}
function on (el, event, handler) {
if (el.addEventListener) {
el.addEventListener(event, handler)
} else {
el.attachEvent('on' + event, function () {
handler.call(el)
})
}
}
}())</script>
</body>
</html>