Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Initial commit.

  • Loading branch information...
commit d304a585630bcc30b8ef17051e104d848fc211d5 0 parents
cloudhead authored
179 LICENSE
... ... @@ -0,0 +1,179 @@
  1 +
  2 + Apache License
  3 + Version 2.0, January 2004
  4 + http://www.apache.org/licenses/
  5 +
  6 +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
  7 +
  8 +1. Definitions.
  9 +
  10 + "License" shall mean the terms and conditions for use, reproduction,
  11 + and distribution as defined by Sections 1 through 9 of this document.
  12 +
  13 + "Licensor" shall mean the copyright owner or entity authorized by
  14 + the copyright owner that is granting the License.
  15 +
  16 + "Legal Entity" shall mean the union of the acting entity and all
  17 + other entities that control, are controlled by, or are under common
  18 + control with that entity. For the purposes of this definition,
  19 + "control" means (i) the power, direct or indirect, to cause the
  20 + direction or management of such entity, whether by contract or
  21 + otherwise, or (ii) ownership of fifty percent (50%) or more of the
  22 + outstanding shares, or (iii) beneficial ownership of such entity.
  23 +
  24 + "You" (or "Your") shall mean an individual or Legal Entity
  25 + exercising permissions granted by this License.
  26 +
  27 + "Source" form shall mean the preferred form for making modifications,
  28 + including but not limited to software source code, documentation
  29 + source, and configuration files.
  30 +
  31 + "Object" form shall mean any form resulting from mechanical
  32 + transformation or translation of a Source form, including but
  33 + not limited to compiled object code, generated documentation,
  34 + and conversions to other media types.
  35 +
  36 + "Work" shall mean the work of authorship, whether in Source or
  37 + Object form, made available under the License, as indicated by a
  38 + copyright notice that is included in or attached to the work
  39 + (an example is provided in the Appendix below).
  40 +
  41 + "Derivative Works" shall mean any work, whether in Source or Object
  42 + form, that is based on (or derived from) the Work and for which the
  43 + editorial revisions, annotations, elaborations, or other modifications
  44 + represent, as a whole, an original work of authorship. For the purposes
  45 + of this License, Derivative Works shall not include works that remain
  46 + separable from, or merely link (or bind by name) to the interfaces of,
  47 + the Work and Derivative Works thereof.
  48 +
  49 + "Contribution" shall mean any work of authorship, including
  50 + the original version of the Work and any modifications or additions
  51 + to that Work or Derivative Works thereof, that is intentionally
  52 + submitted to Licensor for inclusion in the Work by the copyright owner
  53 + or by an individual or Legal Entity authorized to submit on behalf of
  54 + the copyright owner. For the purposes of this definition, "submitted"
  55 + means any form of electronic, verbal, or written communication sent
  56 + to the Licensor or its representatives, including but not limited to
  57 + communication on electronic mailing lists, source code control systems,
  58 + and issue tracking systems that are managed by, or on behalf of, the
  59 + Licensor for the purpose of discussing and improving the Work, but
  60 + excluding communication that is conspicuously marked or otherwise
  61 + designated in writing by the copyright owner as "Not a Contribution."
  62 +
  63 + "Contributor" shall mean Licensor and any individual or Legal Entity
  64 + on behalf of whom a Contribution has been received by Licensor and
  65 + subsequently incorporated within the Work.
  66 +
  67 +2. Grant of Copyright License. Subject to the terms and conditions of
  68 + this License, each Contributor hereby grants to You a perpetual,
  69 + worldwide, non-exclusive, no-charge, royalty-free, irrevocable
  70 + copyright license to reproduce, prepare Derivative Works of,
  71 + publicly display, publicly perform, sublicense, and distribute the
  72 + Work and such Derivative Works in Source or Object form.
  73 +
  74 +3. Grant of Patent License. Subject to the terms and conditions of
  75 + this License, each Contributor hereby grants to You a perpetual,
  76 + worldwide, non-exclusive, no-charge, royalty-free, irrevocable
  77 + (except as stated in this section) patent license to make, have made,
  78 + use, offer to sell, sell, import, and otherwise transfer the Work,
  79 + where such license applies only to those patent claims licensable
  80 + by such Contributor that are necessarily infringed by their
  81 + Contribution(s) alone or by combination of their Contribution(s)
  82 + with the Work to which such Contribution(s) was submitted. If You
  83 + institute patent litigation against any entity (including a
  84 + cross-claim or counterclaim in a lawsuit) alleging that the Work
  85 + or a Contribution incorporated within the Work constitutes direct
  86 + or contributory patent infringement, then any patent licenses
  87 + granted to You under this License for that Work shall terminate
  88 + as of the date such litigation is filed.
  89 +
  90 +4. Redistribution. You may reproduce and distribute copies of the
  91 + Work or Derivative Works thereof in any medium, with or without
  92 + modifications, and in Source or Object form, provided that You
  93 + meet the following conditions:
  94 +
  95 + (a) You must give any other recipients of the Work or
  96 + Derivative Works a copy of this License; and
  97 +
  98 + (b) You must cause any modified files to carry prominent notices
  99 + stating that You changed the files; and
  100 +
  101 + (c) You must retain, in the Source form of any Derivative Works
  102 + that You distribute, all copyright, patent, trademark, and
  103 + attribution notices from the Source form of the Work,
  104 + excluding those notices that do not pertain to any part of
  105 + the Derivative Works; and
  106 +
  107 + (d) If the Work includes a "NOTICE" text file as part of its
  108 + distribution, then any Derivative Works that You distribute must
  109 + include a readable copy of the attribution notices contained
  110 + within such NOTICE file, excluding those notices that do not
  111 + pertain to any part of the Derivative Works, in at least one
  112 + of the following places: within a NOTICE text file distributed
  113 + as part of the Derivative Works; within the Source form or
  114 + documentation, if provided along with the Derivative Works; or,
  115 + within a display generated by the Derivative Works, if and
  116 + wherever such third-party notices normally appear. The contents
  117 + of the NOTICE file are for informational purposes only and
  118 + do not modify the License. You may add Your own attribution
  119 + notices within Derivative Works that You distribute, alongside
  120 + or as an addendum to the NOTICE text from the Work, provided
  121 + that such additional attribution notices cannot be construed
  122 + as modifying the License.
  123 +
  124 + You may add Your own copyright statement to Your modifications and
  125 + may provide additional or different license terms and conditions
  126 + for use, reproduction, or distribution of Your modifications, or
  127 + for any such Derivative Works as a whole, provided Your use,
  128 + reproduction, and distribution of the Work otherwise complies with
  129 + the conditions stated in this License.
  130 +
  131 +5. Submission of Contributions. Unless You explicitly state otherwise,
  132 + any Contribution intentionally submitted for inclusion in the Work
  133 + by You to the Licensor shall be under the terms and conditions of
  134 + this License, without any additional terms or conditions.
  135 + Notwithstanding the above, nothing herein shall supersede or modify
  136 + the terms of any separate license agreement you may have executed
  137 + with Licensor regarding such Contributions.
  138 +
  139 +6. Trademarks. This License does not grant permission to use the trade
  140 + names, trademarks, service marks, or product names of the Licensor,
  141 + except as required for reasonable and customary use in describing the
  142 + origin of the Work and reproducing the content of the NOTICE file.
  143 +
  144 +7. Disclaimer of Warranty. Unless required by applicable law or
  145 + agreed to in writing, Licensor provides the Work (and each
  146 + Contributor provides its Contributions) on an "AS IS" BASIS,
  147 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  148 + implied, including, without limitation, any warranties or conditions
  149 + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
  150 + PARTICULAR PURPOSE. You are solely responsible for determining the
  151 + appropriateness of using or redistributing the Work and assume any
  152 + risks associated with Your exercise of permissions under this License.
  153 +
  154 +8. Limitation of Liability. In no event and under no legal theory,
  155 + whether in tort (including negligence), contract, or otherwise,
  156 + unless required by applicable law (such as deliberate and grossly
  157 + negligent acts) or agreed to in writing, shall any Contributor be
  158 + liable to You for damages, including any direct, indirect, special,
  159 + incidental, or consequential damages of any character arising as a
  160 + result of this License or out of the use or inability to use the
  161 + Work (including but not limited to damages for loss of goodwill,
  162 + work stoppage, computer failure or malfunction, or any and all
  163 + other commercial damages or losses), even if such Contributor
  164 + has been advised of the possibility of such damages.
  165 +
  166 +9. Accepting Warranty or Additional Liability. While redistributing
  167 + the Work or Derivative Works thereof, You may choose to offer,
  168 + and charge a fee for, acceptance of support, warranty, indemnity,
  169 + or other liability obligations and/or rights consistent with this
  170 + License. However, in accepting such obligations, You may act only
  171 + on Your own behalf and on Your sole responsibility, not on behalf
  172 + of any other Contributor, and only if You agree to indemnify,
  173 + defend, and hold each Contributor harmless for any liability
  174 + incurred by, or claims asserted against, such Contributor by reason
  175 + of your accepting any such warranty or additional liability.
  176 +
  177 +END OF TERMS AND CONDITIONS
  178 +
  179 +Copyright (c) 2009-2010 Alexis Sellier
129 README.md
Source Rendered
... ... @@ -0,0 +1,129 @@
  1 +http-console
  2 +============
  3 +
  4 +> Speak HTTP like a local
  5 +
  6 +synopsis
  7 +--------
  8 +
  9 + $ http-console 127.0.0.1:5984
  10 +
  11 + http://127.0.0.1:5984/>
  12 + http://127.0.0.1:5984/> GET /
  13 +
  14 + HTTP/1.1 200 OK
  15 + Date: Mon, 31 May 2010 04:43:39 GMT
  16 + Content-Type: text/plain;charset=utf-8
  17 + Content-Length: 41
  18 +
  19 + {
  20 + couchdb: "Welcome",
  21 + version: "0.11.0"
  22 + }
  23 +
  24 +installation
  25 +------------
  26 +
  27 + $ npm install http-console
  28 +
  29 +introduction
  30 +------------
  31 +
  32 +Let's assume we have a [CouchDB](http://couchdb.apache.org) instance running locally.
  33 +
  34 +### connecting #
  35 +
  36 +To connect, we run `http-console`, passing it the server host and port as such:
  37 +
  38 + $ http-console 127.0.0.1:5984
  39 +
  40 +To have line-editing and command history, we can run it through `rlwrap`:
  41 +
  42 + $ rlwrap http-console 127.0.0.1:5984
  43 +
  44 +### navigating #
  45 +
  46 +Once connected, we should see the *http prompt*:
  47 +
  48 + http://127.0.0.1:5984/>
  49 +
  50 +server navigation is similar to directory navigation, except a little simpler:
  51 +
  52 + http://127.0.0.1:5984/> /logs
  53 + http://127.0.0.1:5984/logs> /46
  54 + http://127.0.0.1:5984/logs/46> ..
  55 + http://127.0.0.1:5984/logs> ..
  56 + http://127.0.0.1:5984/>
  57 +
  58 +### requesting #
  59 +
  60 +HTTP requests are issued with the HTTP verbs *GET*, *PUT*, *POST*, *HEAD* and *DELETE*, and
  61 +a relative path:
  62 +
  63 + http://127.0.0.1:5984/> GET /
  64 + HTTP/1.1 200 OK
  65 + Date: Mon, 31 May 2010 04:43:39 GMT
  66 + Content-Length: 41
  67 +
  68 + {
  69 + couchdb: "Welcome",
  70 + version: "0.11.0"
  71 + }
  72 +
  73 + http://127.0.0.1:5984/> GET /bob
  74 + HTTP/1.1 404 Not Found
  75 + Date: Mon, 31 May 2010 04:45:32 GMT
  76 + Content-Length: 44
  77 +
  78 + {
  79 + error: "not_found",
  80 + reason: "no_db_file"
  81 + }
  82 +
  83 +When issuing *POST* and *PUT* commands, we have the opportunity to send data too:
  84 +
  85 + http://127.0.0.1:5984/> /rabbits
  86 + http://127.0.0.1:5984/rabbits> POST
  87 + ... {"name":"Roger"}
  88 +
  89 + HTTP/1.1 201 Created
  90 + Location: http://127.0.0.1/test/2fd9db055885e6982462a10e54003127
  91 + Date: Mon, 31 May 2010 05:09:15 GMT
  92 + Content-Length: 95
  93 +
  94 + {
  95 + ok: true,
  96 + id: "2fd9db055885e6982462a10e54003127",
  97 + rev: "1-0c3db91854f26486d1c3922f1a651d86"
  98 + }
  99 +
  100 +Note that `POST /` is equivalent to just `POST`. This applies to all methods.
  101 +
  102 +### setting headers #
  103 +
  104 +Sometimes, it's useful to set HTTP headers:
  105 +
  106 + http://127.0.0.1:5984/> Accept: application/json
  107 + http://127.0.0.1:5984/> X-Lodge: black
  108 +
  109 +These headers are sent with all requests in this session. To see all active headers,
  110 +run the `\headers` command:
  111 +
  112 + http://127.0.0.1:5984/> \headers
  113 + Accept: application/json
  114 + X-Lodge: black
  115 +
  116 +Removing headers is just as easy:
  117 +
  118 + http://127.0.0.1:5984/> Accept:
  119 + http://127.0.0.1:5984/> \headers
  120 + X-Lodge: black
  121 +
  122 +### quitting #
  123 +
  124 + Ctrl-D
  125 +
  126 +nuff' said.
  127 +
  128 +
  129 +
19 bin/http-console
... ... @@ -0,0 +1,19 @@
  1 +#!/usr/bin/env node
  2 +
  3 +var path = require('path');
  4 +
  5 +require.paths.unshift(path.join(__dirname, '..', 'lib'));
  6 +
  7 +var parselmouth = require('parselmouth');
  8 +
  9 +var argv = process.argv.slice(2),
  10 + hostPort = argv.length ? argv.shift().replace('http://', '').split(':') : [],
  11 + host = hostPort[0] || '127.0.0.1',
  12 + port = hostPort[1] || 80
  13 + options = {};
  14 +
  15 +var console = new(parselmouth.Console)(host, port, options);
  16 +
  17 +console.initialize();
  18 +
  19 +
169 lib/http-console.js
... ... @@ -0,0 +1,169 @@
  1 +
  2 +var http = require('http'),
  3 + events = require('events'),
  4 + sys = require('sys');
  5 +
  6 +var inspect = require('eyes').inspector();
  7 +var consoles = [];
  8 +
  9 +this.Console = function (host, port, options) {
  10 + this.host = host;
  11 + this.port = port;
  12 + this.options = options;
  13 + this.path = [];
  14 + this.socket = null;
  15 + consoles.push(this);
  16 +};
  17 +
  18 +this.Console.prototype = new(function () {
  19 + this.initialize = function () {
  20 + var that = this;
  21 +
  22 + this.socket = http.createClient(this.port, this.host);
  23 + this.headers = { 'Accept':'*/*' };
  24 +
  25 + this.stdin = process.openStdin();
  26 + this.stdin.setEncoding('ascii');
  27 + this.stdin.addListener('data', function (str) {
  28 + that.exec(str.trim());
  29 + });
  30 + this.prompt();
  31 +
  32 + return this;
  33 + };
  34 + this.request = function (method, path, callback) {
  35 + var request;
  36 +
  37 + this.headers['Host'] = this.host;
  38 +
  39 + request = this.socket.request(method.toUpperCase(),
  40 + path.replace('//', '/'),
  41 + this.headers);
  42 +
  43 + request.addListener('response', function (res) {
  44 + var body = "";
  45 + res.addListener('data', function (chunk) { body += chunk });
  46 + res.addListener('end', function () { callback(res, body) });
  47 + });
  48 +
  49 + return request;
  50 + };
  51 + this.exec = function (command) {
  52 + var method, headers = {}, path = this.path, body,
  53 + that = this;
  54 +
  55 + if (this.waitingForData) {
  56 + this.waitingForData.write(command);
  57 + this.waitingForData.end();
  58 + this.waitingForData = false;
  59 + return;
  60 + } else if (command[0] === '/') {
  61 + Array.prototype.push.apply(
  62 + this.path, command.split('/').filter(function (e) { return e })
  63 + );
  64 + } else if (command === '..') {
  65 + this.path.pop();
  66 + } else if (command[0] === '\\') {
  67 + switch (command.slice(1)) {
  68 + case 'headers':
  69 + this.printHeaders(this.headers);
  70 + break;
  71 + }
  72 + } else if (match = command.match(/([a-zA-Z-]+):\s*(.*)/)) {
  73 + if (match[2]) {
  74 + this.headers[match[1]] = match[2];
  75 + } else {
  76 + delete(this.headers[match[1]]);
  77 + }
  78 + } else if (/^(GET|POST|PUT|HEAD|DELETE)/.test(command)) {
  79 + command = command.split(/\s+/);
  80 + method = command.shift();
  81 + path = '/' + this.path.concat(command.shift()).join('/');
  82 +
  83 + if (method === 'PUT' || method === 'POST') {
  84 + this.waitingForData = this.request(method, path, function (res, body) {
  85 + that.printResponse.call(that, res, body);
  86 + that.prompt();
  87 + });
  88 + this.dataPrompt();
  89 + } else {
  90 + this.request(method, path, function (res, body) {
  91 + that.printResponse.call(that, res, body);
  92 + that.prompt();
  93 + }).end();
  94 + }
  95 + return;
  96 + } else if (command) {
  97 + sys.puts(("unknown command '" + command + "'").yellow.bold);
  98 + }
  99 + this.prompt();
  100 + };
  101 + this.printResponse = function (res, body) {
  102 + var status = ('HTTP/' + res.httpVersion +
  103 + ' ' + res.statusCode +
  104 + ' ' + http.STATUS_CODES[res.statusCode]).bold;
  105 +
  106 + if (res.statusCode >= 500) { status = status.red }
  107 + else if (res.statusCode >= 400) { status = status.yellow }
  108 + else { status = status.green }
  109 +
  110 + sys.puts(status);
  111 +
  112 + this.printHeaders(res.headers);
  113 +
  114 + sys.print('\n');
  115 +
  116 + try { inspect(JSON.parse(body)) }
  117 + catch (_) { sys.print(body.trim().cyan + '\n') }
  118 + };
  119 + this.prompt = function () {
  120 + sys.print(('http://' + this.host + ':' + this.port + '/' + this.path.join('/') + '> ').grey);
  121 + };
  122 + this.dataPrompt = function () {
  123 + sys.print('... '.grey);
  124 + };
  125 + this.printHeaders = function (headers) {
  126 + Object.keys(headers).forEach(function (k) {
  127 + var key = k.replace(/\b([a-z])/g, function (_, m) {
  128 + return m.toUpperCase();
  129 + }).bold;
  130 + sys.puts(key + ': ' + headers[k]);
  131 + });
  132 + };
  133 +});
  134 +
  135 +process.addListener('uncaughtException', function (e) {
  136 + sys.puts(('Error: ' + e.message).red);
  137 + process.exit(-1);
  138 +});
  139 +
  140 +process.addListener('exit', function () {
  141 + consoles.forEach(function (c) {
  142 + c.socket.destroy();
  143 + });
  144 + sys.print('\n');
  145 +});
  146 +
  147 +['bold', 'grey', 'yellow', 'green', 'cyan'].forEach(function (style) {
  148 + Object.defineProperty(String.prototype, style, {
  149 + get: function () {
  150 + return stylize(this, style);
  151 + }
  152 + });
  153 +});
  154 +
  155 +
  156 +function stylize(str, style) {
  157 + var styles = {
  158 + 'bold' : [1, 22],
  159 + 'italic' : [3, 23],
  160 + 'underline' : [4, 24],
  161 + 'yellow' : [33, 39],
  162 + 'cyan' : [37, 39],
  163 + 'green' : [32, 39],
  164 + 'red' : [31, 39],
  165 + 'grey' : [90, 39],
  166 + };
  167 + return '\033[' + styles[style][0] + 'm' + str +
  168 + '\033[' + styles[style][1] + 'm';
  169 +};
14 package.json
... ... @@ -0,0 +1,14 @@
  1 +{
  2 + "name" : "http-console",
  3 + "description" : "Speak HTTP like a native",
  4 + "url" : "http://github.com/cloudhead/http-console",
  5 + "keywords" : ["http", "console"],
  6 + "author" : "Alexis Sellier <self@cloudhead.net>",
  7 + "contributors" : [],
  8 + "dependencies" : { "eyes": ">=0.1.0" },
  9 + "version" : "0.1.0",
  10 + "main" : "./lib/http-console",
  11 + "directories" : { "lib": "./lib", "test": "./test" },
  12 + "bin" : { "http-console": "./bin/http-console" },
  13 + "engines" : { "node": ">=0.1.93" }
  14 +}

0 comments on commit d304a58

Please sign in to comment.
Something went wrong with that request. Please try again.