diff options
Diffstat (limited to 'go')
-rw-r--r-- | go/Makefile | 35 | ||||
-rw-r--r-- | go/README.markdown | 54 | ||||
-rw-r--r-- | go/etc/conf.d/go.env | 2 | ||||
-rw-r--r-- | go/etc/systemd/system/go.service | 14 | ||||
-rw-r--r-- | go/index.js | 106 | ||||
-rw-r--r-- | go/package.json | 10 | ||||
-rwxr-xr-x | go/t/docker/docker_deploy.sh | 20 | ||||
-rw-r--r-- | go/t/docker/dockertest/deploy | 11 |
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 . |