diff --git a/Procfile b/Procfile index 15a4ec8..063b78f 100644 --- a/Procfile +++ b/Procfile @@ -1 +1 @@ -web: npm config set httpconsole:port_mask 80 && npm start +web: npm start diff --git a/README.md b/README.md index 7e2504f..124ff84 100644 --- a/README.md +++ b/README.md @@ -61,12 +61,6 @@ By Default the server will run on port `8080`, you can customize the port like s npm config set httpconsole:port 8001 ``` -**note**: in environments such as Heroku, the port which the server is running on, is forwarded to another, by default the application will use the port defined above in all responses (e.g. redirects), if you wish to use a masked port, set the following config: - -```shell -npm config set httpconsole:port_mask 80 -``` - *read more on [Configuration](docs/config.md)*. ### Running diff --git a/package.json b/package.json index ba77d6b..b8da944 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,6 @@ "har-validator": "^1.0.2", "hiredis": "^0.2.0", "jade": "^1.9.2", - "marked": "^0.3.3", "media-typer": "^0.3.0", "method-override": "^2.3.1", "morgan": "^1.5.1", diff --git a/server.js b/server.js index d70c3dc..bae2698 100644 --- a/server.js +++ b/server.js @@ -14,7 +14,6 @@ var url = require('url'); // default configs var config = rc('httpconsole', { port: process.env.npm_package_config_port, - port_mask: process.env.npm_package_config_port_mask, redis: process.env.npm_package_config_redis, quiet: process.env.npm_package_config_quiet === 'false' ? false : true }); @@ -42,7 +41,7 @@ var app = express(); app.set('jsonp callback name', '__callback'); app.set('view engine', 'jade'); -app.enable('view cache'); +//app.enable('view cache'); app.enable('trust proxy'); // add 3rd party middlewares diff --git a/src/index.js b/src/index.js index b25eac1..f0606f7 100644 --- a/src/index.js +++ b/src/index.js @@ -7,9 +7,6 @@ var mw = require('./middleware'); module.exports = function (config, redis) { var router = express.Router(); - // add httpconsole middlewares - // router.use(mw.utilMiddleware); - router.get('/', mw.errorHandler, mw.cors, mw.bodyParser, routes.hello, mw.negotiateContent); router.all('/ip', mw.errorHandler, mw.cors, mw.bodyParser, routes.ips.one, mw.negotiateContent); diff --git a/src/middleware/negotiate-content.js b/src/middleware/negotiate-content.js index 412e787..04fad4b 100644 --- a/src/middleware/negotiate-content.js +++ b/src/middleware/negotiate-content.js @@ -34,22 +34,18 @@ module.exports = function (req, res, next) { } function HTMLResponse () { - res.locals.path = req.path; - res.locals.hostname = req.hostname; + res.locals.req = req; res.render(res.view || 'default', { data: { raw: res.body, - yaml: YAML.stringify(res.body, res.yamlInline || 3, spaces), + yaml: YAML.stringify(res.body, res.yamlInline || 3, 2), - json: JSON.stringify(res.body, null, spaces), + json: JSON.stringify(res.body, null, 2), - xml: XML.create(res.bodyXmlObj || res.body, { - prettyPrint: true, - indent: spaces - }).end({ + xml: XML.create(res.bodyXmlObj || res.body).end({ pretty: true, - indent: spaces, + indent: ' ', newline: '\n' }) } diff --git a/src/routes/buckets.js b/src/routes/buckets.js index e159294..1009299 100644 --- a/src/routes/buckets.js +++ b/src/routes/buckets.js @@ -32,7 +32,7 @@ module.exports = { res.status(201); // send back the newly created id - res.body = util.format('http://%s:%s/bucket/%s', req.hostname, config.port_mask || config.port, id); + res.body = util.format('/bucket/%s', id); res.location(res.body); next(); diff --git a/src/routes/headers.js b/src/routes/headers.js index b5d690b..ee2db2b 100644 --- a/src/routes/headers.js +++ b/src/routes/headers.js @@ -2,6 +2,8 @@ module.exports = { all: function (req, res, next) { + res.yamlInline = 2; + res.status(200).body = { headers: req.har.log.entries[0].request.headers, headersSize: req.har.log.entries[0].request.headersSize diff --git a/views/404.jade b/views/404.jade index 262a2be..76ffcc9 100644 --- a/views/404.jade +++ b/views/404.jade @@ -1,4 +1,5 @@ extends layout.jade block content - h1 404 + div.container + h1 404 diff --git a/views/bucket/create.jade b/views/bucket/create.jade index d73cefe..dc13574 100644 --- a/views/bucket/create.jade +++ b/views/bucket/create.jade @@ -1,24 +1,25 @@ extends ../layout.jade block content - form - div.form-group - label(for='exampleInputEmail1') Email address - input.form-control(type='email', placeholder='Enter email') + div.container + form + div.form-group + label(for='exampleInputEmail1') Email address + input.form-control(type='email', placeholder='Enter email') - div.form-group - label(for='exampleInputPassword1') Password - input.form-control(type='password', placeholder='Password') + div.form-group + label(for='exampleInputPassword1') Password + input.form-control(type='password', placeholder='Password') - div.form-group - label(for='exampleInputFile') File input - input(type='file') - p.help-block Example block-level help text here. + div.form-group + label(for='exampleInputFile') File input + input(type='file') + p.help-block Example block-level help text here. - div.checkbox - label - input(type='checkbox') - | Check me out + div.checkbox + label + input(type='checkbox') + | Check me out - button.btn.btn-default(type='submit') Submit + button.btn.btn-default(type='submit') Submit diff --git a/views/bucket/log.jade b/views/bucket/log.jade index 12039a6..7d0fd2a 100644 --- a/views/bucket/log.jade +++ b/views/bucket/log.jade @@ -1,21 +1,22 @@ extends ../layout.jade block content - pre: code= YAML.stringify(data, 6, 2) + div.container + pre: code= YAML.stringify(data, 6, 2) - for entry in data.log.entries - div - strong #{entry.request.method} - span (#{entry.request.bodySize} bytes) - span From #{entry.clientIPAddress} + for entry in data.log.entries + div + strong #{entry.request.method} + span (#{entry.request.bodySize} bytes) + span From #{entry.clientIPAddress} - h6 Headers - pre: code - - for header in entry.request.headers - | #{header.name}: #{header.value} + h6 Headers + pre: code + - for header in entry.request.headers + | #{header.name}: #{header.value} - h6 postData - pre: code= YAML.stringify(entry.request.postData, 2, 2) + h6 postData + pre: code= YAML.stringify(entry.request.postData, 2, 2) - h6 Query - pre: code= YAML.stringify(entry.request.queryString, 2, 2) + h6 Query + pre: code= YAML.stringify(entry.request.queryString, 2, 2) diff --git a/views/bucket/view.jade b/views/bucket/view.jade index 449bc34..22f4eb8 100644 --- a/views/bucket/view.jade +++ b/views/bucket/view.jade @@ -1,12 +1,13 @@ extends ../layout.jade block content - ul(class='nav nav-tabs') - li(class='active'): a(href='#home', data-toggle='tab') YAML - li: a(href='#json', data-toggle='tab') JSON - li: a(href='#xml', data-toggle='tab') XML + div.container + ul(class='nav nav-tabs') + li(class='active'): a(href='#home', data-toggle='tab') YAML + li: a(href='#json', data-toggle='tab') JSON + li: a(href='#xml', data-toggle='tab') XML - div(class='tab-content') - div(class='tab-pane active', id='home'): pre: code= data.yaml - div(class='tab-pane', id='json'): pre: code= data.json - div(class='tab-pane', id='xml'): pre: code= data.xml + div(class='tab-content') + div(class='tab-pane active', id='home'): pre: code= data.yaml + div(class='tab-pane', id='json'): pre: code= data.json + div(class='tab-pane', id='xml'): pre: code= data.xml diff --git a/views/default.jade b/views/default.jade index 431fb85..6bd31b5 100644 --- a/views/default.jade +++ b/views/default.jade @@ -1,41 +1,49 @@ extends layout.jade block content - if (data) - ul(class='nav nav-pills') - li.active: a(href='#yaml', data-toggle='tab') YAML - li: a(href='#json', data-toggle='tab') JSON - li: a(href='#xml', data-toggle='tab') XML + div.container + if (!data) + div.alert.alert-warning No data - hr + else + div#preview + button(class='btn btn-default btn-clipboard', data-clipboard-target='#{target}'): i.fa.fa-copy - p calling http://#{hostname}#{path} with an Accept header with the value:   - select - for value, key in {yaml: 'application/x-yaml', json: 'application/json', 'xml': 'application/xml'} - option(value= key)= value - | will result in the content below: + ul.nav.nav-tabs + li.active: a(href='#json', data-toggle='tab') JSON + li: a(href='#yaml', data-toggle='tab') YAML + li: a(href='#xml', data-toggle='tab') XML - div(class='tab-content') - div(id='yaml').tab-pane.active.fade.in - pre: code= data.yaml + div.tab-content + div(id='json').tab-pane.active.fade.in + pre: code= data.json - div(id='json').tab-pane.fade - pre: code= data.json + div(id='yaml').tab-pane.fade + pre: code= data.yaml - div(id='xml').tab-pane.fade - pre: code= data.xml + div(id='xml').tab-pane.fade + pre: code= data.xml - p for more info, review the  - a(href='/docs#' + path.replace('/', '-') + '-') documentation + br - //- hr - //- p Try this request with + p: em You're viewing the HTML output, try calling this endpoint with an #[code Accept] header with one of the values: #[code application/x-yaml], #[code application/json], #[code application/xml] block scripts script(type='text/javascript'). - $('select').on('click', function () { - event.preventDefault(); - - $('[href=#' + $(this).val() + ']').tab('show') + $(function() { + ZeroClipboard.config({ + swfPath: '//cdnjs.cloudflare.com/ajax/libs/zeroclipboard/2.2.0/ZeroClipboard.swf', + forceHandCursor: true, + trustedDomains: [window.location.host, "cdnjs.cloudflare.com"] + }); + + new ZeroClipboard($('.btn-clipboard')); + + // select first tab + $('.nav-tabs a:first').tab('show'); + + // highlight the code + $('.tab-content pre code').each(function (i, block) { + hljs.highlightBlock(block); + }); }); - diff --git a/views/layout.jade b/views/layout.jade index 05ca0d5..ef661b1 100644 --- a/views/layout.jade +++ b/views/layout.jade @@ -6,13 +6,188 @@ html title HTTP Console link(rel='stylesheet', type='text/css', href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/css/bootstrap.min.css', media='all') + link(rel='stylesheet', type='text/css', href='https://fonts.googleapis.com/css?family=Open+Sans:400,600|Source+Code+Pro:200,300,400,500,600,700,900', media='all') + link(rel='stylesheet', type='text/css', href='https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.css', media='all') + link(rel='stylesheet', type='text/css', href='https://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/styles/tomorrow.min.css', media='all') + + script(type='text/javascript', src='https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js') + script(type='text/javascript', src='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.1/js/bootstrap.min.js') + script(type='text/javascript', src='https://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/highlight.min.js') + script(type='text/javascript', src='https://cdnjs.cloudflare.com/ajax/libs/zeroclipboard/2.2.0/ZeroClipboard.min.js') + + style. + * { + -webkit-font-smoothing:antialiased; + -moz-osx-font-smoothing:grayscale; + } + + body { + color: #36434C; + font-family: 'Open Sans', helvetica, sans-serif; + + padding: 50px; + } + + code, kbd, pre, samp { + font-family: 'Source Code Pro', Menlo, Monaco, Consolas, 'Courier New', monospace; + } + + #preview { + position: relative; + + border-radius: 4px; + border: 1px solid #C7C7C7; + border: 1px solid rgba(0, 0, 0, .22); + background-color: #FFFFFF; + + box-shadow: 1px 0px 3px rgba(0, 0, 0, .15); + + -moz-background-clip: padding; + -webkit-background-clip: padding-box; + background-clip: padding-box; + } + + #preview .nav-tabs { + border-color: #EAEAEA; + background-color: #FCFCFC; + } + + #preview .nav-tabs > li a, + #preview .nav-tabs > li a:focus { + border-top: none; + border-bottom: none; + border-radius: 0; + + color: #8C9093; + font-size: 13px; + font-weight: 600; + padding: 16px; + } + + #preview .nav-tabs > li a:hover { + color: #41484C; + background-color: #FCFCFC; + } + + #preview .nav-tabs .open > a { + border-color: #E6E6E6; + background-color: #FCFCFC; + } + + #preview .nav-tabs > li.active > a, + #preview .nav-tabs > li.active > a:focus, + #preview .nav-tabs > li.active > a:hover { + color: #216FA6; + border-color: #E6E6E6; + } + + #preview .nav-tabs > .dropdown.active > a { + color: #41484C; + } + + #preview .nav-tabs > .dropdown > .dropdown-menu a .fa { + opacity: 0; + } + + #preview .nav-tabs > .dropdown.active > .dropdown-menu > .active > a .fa { + opacity: 1; + } + + #preview .nav-tabs > .dropdown.active > .dropdown-menu > .active > a, + #preview .nav-tabs > .dropdown.active > .dropdown-menu > .active > a:focus, + #preview .nav-tabs > .dropdown.active > .dropdown-menu > .active > a:hover { + color: #216FA6; + background-color: #F2F9FF; + } + + #preview .dropdown-menu { + padding: 0; + border-radius: 0; + + border-top: 0; + margin-top: 0; + + background-color: #FCFCFC; + box-shadow: 1px 0px 4px rgba(0, 0, 0, .15); + } + + #preview .nav-tabs { + border-top-left-radius: 4px; + border-top-right-radius: 4px; + } + + #preview .nav-tabs > li:hover a { + background-color: #FFFFFF; + } + + #preview .nav-tabs > li:first-of-type > a { + border-left: none; + border-top-left-radius: 4px; + } + + #preview .tab-content .tab-pane, + #preview .tab-content .tab-pane pre, + #preview .tab-content .tab-pane pre code { + min-height: 300px; + } + + #preview .btn-clipboard { + position: absolute; + top: 5px; + right: 5px; + + color: #AAAFB3; + border-color: #D7D9DB + + background: #053b7b; + background: -moz-linear-gradient(0deg, #FFFFFF 0%, #F7F7F7 100%); + background: -webkit-linear-gradient(0deg, #FFFFFF 0%, #F7F7F7 100%); + background: -o-linear-gradient(0deg, #FFFFFF 0%, #F7F7F7 100%); + background: -ms-linear-gradient(0deg, #FFFFFF 0%, #F7F7F7 100%); + background: linear-gradient(0deg, #FFFFFF 0%, #F7F7F7 100%); + } + + #preview footer { + padding: 10px 15px; + + color: #7b858c; + font-size: 11px; + font-weight: 600; + + border-top: 1px solid #E6E6E6; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + + background-color: #FFFFFF; + } + + #preview footer a { + color: #399ee5; + } + + #preview pre { + margin: 0; + padding: 0; + + border: none; + border-radius: 0; + + background-color: #FFFFFF; + } + + #preview pre code { + padding: 15px; + } + + .hljs { + padding: 0; + } block head body block header - div.container-fluid - block content + block content block scripts