summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.markdown54
-rw-r--r--index.js106
-rw-r--r--package.json10
3 files changed, 170 insertions, 0 deletions
diff --git a/README.markdown b/README.markdown
new file mode 100644
index 0000000..22b7c64
--- /dev/null
+++ b/README.markdown
@@ -0,0 +1,54 @@
+# go - minimalistic uri shortener
+
+## install dependencies
+
+ npm install
+
+ apparently you can also
+
+ npm install hiredis
+
+ for more awesome.
+
+## run service
+
+ PORT=80 node .
+
+ if you omit `PORT`, then it's `1337`.
+
+ there's also the possibility to change the Redis key prefix which
+ defaults to `go:` with
+
+ REDIS_KEY_PREFIX=foobarmyprefix/
+
+## add uri
+
+ curl -F uri=https://mywaytoolonguri http://localhost:1337
+
+ this will give you a shortened uri.
+
+## resolve uri
+
+ curl -L http://localhost:1337/1
+
+## clear database
+
+ redis-cli keys 'go:*' | xargs redis-cli del
+
+ if you have changed `redisPrefix`, then use that instead of `go:`.
+
+## use systemd
+
+ run
+
+ make install
+
+ to install the systemd service and configuration files.
+ this will fail if the files are already installed and modified.
+
+ configure `HOSTN` and `PORT` in `/etc/conf.d/go.env` and the user
+ and/or group in `/etc/systemd/system/go.service`.
+
+ and finally start the service with
+
+ systemctl start go
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..e9b551c
--- /dev/null
+++ b/index.js
@@ -0,0 +1,106 @@
+// configuration
+var httpPort = process.env.PORT;
+var redisPrefix = process.env.REDIS_KEY_PREFIX;
+
+
+// automatic configuration
+if (!httpPort) {
+ httpPort = 1337;
+}
+if (!redisPrefix) {
+ redisPrefix = 'go:';
+}
+
+
+// load libraries
+var http = require('http');
+var url = require('url');
+var formidable = require('formidable');
+var redis = require('redis');
+
+
+// instantiate components
+var redisClient = redis.createClient();
+var httpServer = http.createServer(listener);
+
+
+// setup compoments
+redisClient.on('error', function (err) {
+ console.log('redis made a bubu:', err.message);
+ process.exit(23);
+});
+httpServer.listen(httpPort, function () {
+ console.log('http server listening on port', httpPort);
+});
+
+
+// http handler
+function listener (req, res) {
+ if (req.method === 'POST' && req.url === '/') {
+ return create(req, res);
+ } else if (req.method === 'GET') {
+ return retrieve(req, res);
+ } else {
+ return methodNotAllowed(req, res);
+ }
+}
+
+function create (req, res) {
+ redisClient.incr(redisPrefix + 'index', function (err, reply) {
+ if (err) {
+ return internalError(err, req, res);
+ }
+
+ var form = new formidable.IncomingForm();
+
+ form.parse(req, function(err, fields, files) {
+ if (err) {
+ return internalError(err, req, res);
+ }
+
+ var uri = fields.uri;
+ // TODO check uri(?)
+ var shortPath = '/' + reply;
+ var shortUri = 'http://' + req.headers.host + shortPath;
+ var key = redisPrefix + shortPath;
+
+ redisClient.set(key, uri, function (error) {
+ if (error) {
+ return internalError(err, req, res);
+ }
+
+ res.writeHead(200, { 'content-type': 'text/plain' });
+ return res.end(shortUri + '\r\n');
+ });
+ });
+ });
+}
+
+function retrieve (req, res) {
+ var key = redisPrefix + url.parse(req.url).path;
+ redisClient.get(key, function (error, reply) {
+ if (error) {
+ return internalError(err, req, res);
+ }
+
+ if (typeof reply !== 'string') {
+ res.writeHead(404, { 'content-type': 'text/plain' });
+ return res.end('not found\r\n');
+ }
+
+ res.writeHead(302, {
+ 'content-type': 'text/plain',
+ 'location': reply,
+ });
+ return res.end();
+ });
+}
+
+function methodNotAllowed (req, res) {
+ res.writeHead(405, { 'content-type': 'text/plain' });
+ return res.end('method not allowed\r\n');
+}
+function internalError (error, req, res) {
+ res.writeHead(500, { 'content-type': 'text/plain' });
+ return res.end(error.message + '\r\n');
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..787f281
--- /dev/null
+++ b/package.json
@@ -0,0 +1,10 @@
+{
+ "name": "go",
+ "version": "0.0.0",
+ "description": "minimalistic uri shortener",
+ "dependencies": {
+ "formidable": "*",
+ "redis": "*"
+ },
+ "license": "WTFPL"
+}