├── Procfile ├── app.json ├── README.md ├── package.json ├── LICENSE └── index.js /Procfile: -------------------------------------------------------------------------------- 1 | web: node --optimize_for_size --max_old_space_size=460 --gc_interval=100 index.js 2 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pagehash", 3 | "description": "Hash an HTML page", 4 | "repository": "https://github.com/mermade/pagehash", 5 | "logo": "http://mermade.github.io/arapaho/logo.jpg", 6 | "keywords": ["html","hash","md5","sha1"] 7 | } 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pagehash 2 | Hash a URL's contents 3 | 4 | ## Usage 5 | 6 | `{baseurl}/md5?q={url to hash}` 7 | 8 | or 9 | 10 | `{baseurl}/sha1?q={url to hash}` 11 | 12 | [![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy) 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pagehash", 3 | "version": "1.0.0", 4 | "description": "Hash an HTML page", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Mike Ralphson", 10 | "license": "BSD-3-Clause", 11 | "dependencies": { 12 | "express": "^4.13.3" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2017, Mermade Software 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var crypto = require('crypto'); 3 | var http = require('http'); 4 | var https = require('https'); 5 | var url = require('url'); 6 | 7 | var express = require('express'); 8 | 9 | var app = express(); 10 | 11 | var prefix = 'pagehash'; 12 | var suffix = ''; 13 | 14 | function getHTML(options, onResult) { 15 | 16 | var prot = options.port == 443 ? https : http; 17 | options.headers.Connection = 'keep-alive'; 18 | var req = prot.request(options, function(res) { 19 | var output = ''; 20 | res.setEncoding('utf8'); 21 | 22 | res.on('data', function (chunk) { 23 | output += chunk; 24 | }); 25 | 26 | res.on('end', function() { 27 | if (res.statusCode >= 300 && res.statusCode < 400 && hasHeader('location', res.headers)) { 28 | // handle redirects, as per request module 29 | var location = res.headers[hasHeader('location', res.headers)]; 30 | var locUrl = url.parse(location); 31 | options.path = locUrl.pathname; 32 | options.hostname = locUrl.host; 33 | options.port = locUrl.port; 34 | console.log('Redirecting to '+options.path); 35 | getHTML(options, onResult); 36 | } 37 | else { 38 | onResult(res.statusCode, output); 39 | } 40 | }); 41 | }); 42 | 43 | req.on('error', function(err) { 44 | onResult(500,'error: ' + err.message + ' ' + output); 45 | }); 46 | 47 | req.end(); 48 | } 49 | 50 | function sha1(s) { 51 | var shasum = crypto.createHash('sha1'); 52 | shasum.update(s); 53 | return shasum.digest('hex'); 54 | } 55 | 56 | function md5(s) { 57 | var shasum = crypto.createHash('md5'); 58 | shasum.update(s); 59 | return shasum.digest('hex'); 60 | } 61 | 62 | function respond(req,res,hash){ 63 | if (req.params.hash == 'sha1') hash = sha1(hash); 64 | if (req.params.hash == 'md5') hash = md5(hash); 65 | res.send(prefix+hash+suffix); 66 | } 67 | 68 | app.get('/:hash', function(req,res) { 69 | var hash = ''; 70 | console.log('query: '+JSON.stringify(req.query,null,2)); 71 | if (req.query.q) { 72 | var options = {}; 73 | var u = url.parse(req.query.q); 74 | options.hostname = u.hostname; 75 | options.port = u.port ? u.port : (u.protocol.startsWith('https') ? 443 : 80); 76 | options.method = 'GET'; 77 | options.headers = {}; 78 | options.headers.Accept = 'text/html'; 79 | options.headers["Content-Type"] = 'text/html'; 80 | options.path = u.pathname; 81 | 82 | console.log('URL: '+JSON.stringify(u,null,2)); 83 | console.log('opt: '+JSON.stringify(options,null,2)); 84 | 85 | getHTML(options,function(statusCode,d){ 86 | respond(req,res,d); 87 | }); 88 | } 89 | else respond(req,res,hash); 90 | }); 91 | 92 | var myport = process.env.PORT || 3001; 93 | if (process.argv.length>2) myport = process.argv[2]; 94 | 95 | var server = app.listen(myport, function () { 96 | var host = server.address().address; 97 | var port = server.address().port; 98 | 99 | console.log('pagehash server listening at http://%s:%s', host, port); 100 | }); 101 | --------------------------------------------------------------------------------