summaryrefslogtreecommitdiffstats
path: root/go
diff options
context:
space:
mode:
Diffstat (limited to 'go')
-rw-r--r--go/Makefile35
-rw-r--r--go/README.markdown54
-rw-r--r--go/etc/conf.d/go.env2
-rw-r--r--go/etc/systemd/system/go.service14
-rw-r--r--go/index.js106
-rw-r--r--go/package.json10
-rwxr-xr-xgo/t/docker/docker_deploy.sh20
-rw-r--r--go/t/docker/dockertest/deploy11
8 files changed, 252 insertions, 0 deletions
diff --git a/go/Makefile b/go/Makefile
new file mode 100644
index 00000000..abbaf7fe
--- /dev/null
+++ b/go/Makefile
@@ -0,0 +1,35 @@
+help:;@grep -v ^help: Makefile
+
+install: \
+ /etc/systemd/system/go.service \
+ /etc/conf.d/go.env
+ systemctl daemon-reload
+
+/etc/%: etc/%
+ @! test -e $@ || { echo file already exists: $@; exit 23; }
+ mkdir -p $(dir $@)
+ cp $< $@
+
+test:
+ @export PATH="$(CURDIR)/bin:$(PATH)"; \
+ tests="`find t -type f -executable`"; \
+ i=1; \
+ pids="";\
+ n=`echo "$$tests" | wc -l`; \
+ echo $$i..$$n; \
+ for exe in $$tests; do \
+ { \
+ ./$$exe; \
+ ret=$$?; \
+ case $$ret in 0) result=ok;; *) result='not ok';; esac; \
+ echo $$result $$i - $$exe; \
+ exit $$ret;\
+ } & \
+ pids="$${pids} $$!" \
+ i=$$(( i+1 )); \
+ done; \
+ ret=0;\
+ for pid in $$pids; do \
+ wait $$pid || ret=23;\
+ done; \
+ exit $$ret;
diff --git a/go/README.markdown b/go/README.markdown
new file mode 100644
index 00000000..22b7c642
--- /dev/null
+++ b/go/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/go/etc/conf.d/go.env b/go/etc/conf.d/go.env
new file mode 100644
index 00000000..6045deac
--- /dev/null
+++ b/go/etc/conf.d/go.env
@@ -0,0 +1,2 @@
+PORT=1337
+REDIS_KEY_PREFIX=go:
diff --git a/go/etc/systemd/system/go.service b/go/etc/systemd/system/go.service
new file mode 100644
index 00000000..c129296c
--- /dev/null
+++ b/go/etc/systemd/system/go.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=go uri shortener
+After=redis.service
+
+[Service]
+EnvironmentFile=/etc/conf.d/go.env
+ExecStart=/usr/bin/node /krebs/go
+KillMode=process
+User=go
+Group=go
+Restart=always
+
+[Install]
+WantedBy=multi-user.target
diff --git a/go/index.js b/go/index.js
new file mode 100644
index 00000000..e9b551c0
--- /dev/null
+++ b/go/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/go/package.json b/go/package.json
new file mode 100644
index 00000000..787f2810
--- /dev/null
+++ b/go/package.json
@@ -0,0 +1,10 @@
+{
+ "name": "go",
+ "version": "0.0.0",
+ "description": "minimalistic uri shortener",
+ "dependencies": {
+ "formidable": "*",
+ "redis": "*"
+ },
+ "license": "WTFPL"
+}
diff --git a/go/t/docker/docker_deploy.sh b/go/t/docker/docker_deploy.sh
new file mode 100755
index 00000000..3e64426d
--- /dev/null
+++ b/go/t/docker/docker_deploy.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+cd $(dirname $(readlink -f $0))
+set -xeuf
+rnd_port=$(shuf -i 2000-65000 -n 1)
+docker_id=$(docker run -p $rnd_port:80 -d -v /krebs/go/t/docker/../../../:/krebs ubuntu /bin/bash /krebs/go/t/docker/dockertest/deploy)
+#docker run -p $rnd_port:80 -v /krebs/go/t/docker/../../../:/krebs ubuntu /bin/bash /krebs/go/t/docker/dockertest/deploy
+echo $docker_id on $rnd_port
+trap "docker stop $docker_id;docker rm $docker_id" INT TERM EXIT QUIT
+i=0
+max_wait=60
+echo "waiting for install (takes about 3 minutes)"
+sleep 240
+while ! curl -s localhost:$rnd_port >/dev/null ;do
+ i=$((i+1))
+ test $i -gt $max_wait && echo "timeout for installation reached, bailing out" && exit 1
+ echo "http port not yet reachable ($i of $max_wait). waiting"
+ sleep 10
+done
+short_uri=$(curl -F "uri=aids.balls" localhost:$rnd_port| sed 's/\r$//')
+curl $short_uri -v 2>&1 | grep location: | grep aids.balls
diff --git a/go/t/docker/dockertest/deploy b/go/t/docker/dockertest/deploy
new file mode 100644
index 00000000..399f469c
--- /dev/null
+++ b/go/t/docker/dockertest/deploy
@@ -0,0 +1,11 @@
+#!/bin/sh
+echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
+apt-get update
+apt-get install -y python-software-properties python g++ make
+add-apt-repository -y ppa:chris-lea/node.js
+apt-get update
+apt-get -y install nodejs redis-server
+npm config set registry http://registry.npmjs.org/
+cd /krebs/go
+npm install
+PORT=80 node .