commit 85850a9d63dc8048767ffbbfef3cb21c6cd32156 Author: Raphael Maenle Date: Thu Aug 12 11:45:31 2021 +0200 initial commit, adding flask structure, README, routes - routes defined in routes.py uses the function to catch every non-empty url comming along - request.full_path is used to get the entire url, as would remove eg GET '?' from the url, which we don't want for the link forwarding. - request.full_path[1:] removes the '/' from the url diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c18dd8d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..6a9aaa9 --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +## Link shortener + +this project is a tiny flask implementation that automatically generates +shortened links for any url. + +If you're on a website, `add short.maenle.tech` to the beginning of the url, +and the flask app returns a shortened url that it saves in a json file on the +server and forwards to the original url when accessed. + + +## Further Todos + +- add https encryption +- add uWSGI +- use sqlite3 instead of json + diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 0000000..2abee70 --- /dev/null +++ b/app/__init__.py @@ -0,0 +1,8 @@ +from flask import Flask + + +app = Flask(__name__, + static_folder='static', + template_folder='template') + +from app import routes diff --git a/app/routes.py b/app/routes.py new file mode 100644 index 0000000..83b4ecf --- /dev/null +++ b/app/routes.py @@ -0,0 +1,42 @@ +from flask import render_template,redirect,request, jsonify +from app import app + +import os, json +import random, string + +app.secret_key = os.environ.get("SECRET_KEY") or os.urandom(24) +app.view_functions['static'] + +SHORT_HOST = 'short.maenle.tech' + + +@app.route("/to/", host=SHORT_HOST) +def short(short): + f = open('app/static/res/short.json', 'r') + data = json.load(f) + for s in data: + if s['short'] == short: + return redirect(s['path'], code=302) + + return jsonify(success=False) + +@app.route("/", host=SHORT_HOST) +def long(path): + full_path = request.full_path[1:] + f = open('app/static/res/short.json', 'r') + data = json.load(f) + for s in data: + if s['path'] == full_path: + return jsonify(path="short.maenle.tech/to/"+s['short']) + + letters = string.ascii_lowercase + short = ''.join(random.choice(letters) for i in range(12)) + + data.append({'path': full_path, 'short': short}) + f = open('app/static/res/short.json', 'w') + json.dump(data, f) + f.close() + template = render_template("short.html", path="short.maenle.tech/to/"+short) + return template + + diff --git a/app/static/css/style.css b/app/static/css/style.css new file mode 100644 index 0000000..6653bba --- /dev/null +++ b/app/static/css/style.css @@ -0,0 +1,10 @@ +html +{ + font-family: Segoe UI, Frutiger, sans-serif; + width: 100%; height: 100% +} + +body { + margin: 0px; +} + diff --git a/app/static/res/favicon.ico b/app/static/res/favicon.ico new file mode 100644 index 0000000..774f1ca Binary files /dev/null and b/app/static/res/favicon.ico differ diff --git a/app/static/res/short.json b/app/static/res/short.json new file mode 100644 index 0000000..fe51488 --- /dev/null +++ b/app/static/res/short.json @@ -0,0 +1 @@ +[] diff --git a/app/template/short.html b/app/template/short.html new file mode 100644 index 0000000..a7c45de --- /dev/null +++ b/app/template/short.html @@ -0,0 +1,18 @@ + + + + + + Link Shortening + + + + + +

+ Your Link: +

+ {{ path }} + + + diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 0000000..db506b9 --- /dev/null +++ b/docker/README.md @@ -0,0 +1,7 @@ +## Goal + +run short-server in a docker-compose environment + +## Usage + +1. `docker-compose up -d` starts the containers in background diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000..fd56b22 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,28 @@ +version: '3' +services: + short-server: + build: + context: ./short-server + image: daria/short-server:latest + container_name: short-server + environment: + - FLASK_APP=/home/short-server/server.py + - FLASK_ENV=development + volumes: + - ../:/home/short-server + ports: + - "0.0.0.0:8086:8086" + networks: + net: + ipv4_address: '172.25.0.12' + +volumes: + database: + driver: local + +networks: + net: + ipam: + driver: default + config: + - subnet: 172.25.0.0/24 diff --git a/docker/short-server/Dockerfile b/docker/short-server/Dockerfile new file mode 100644 index 0000000..3d2b44a --- /dev/null +++ b/docker/short-server/Dockerfile @@ -0,0 +1,8 @@ +FROM python:3.8-slim-buster +RUN apt-get update && apt-get upgrade -y +RUN apt-get install gcc libmariadbclient-dev -y +RUN pip3 install google-oauth google-api-python-client +RUN pip3 install flask Flask-SQLAlchemy flask_migrate flask_wtf python-dotenv mysqlclient +COPY docker-entrypoint.sh /usr/local/bin/ +EXPOSE 3001 +ENTRYPOINT ["docker-entrypoint.sh"] diff --git a/docker/short-server/docker-entrypoint.sh b/docker/short-server/docker-entrypoint.sh new file mode 100755 index 0000000..50bbc64 --- /dev/null +++ b/docker/short-server/docker-entrypoint.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e + +sleep 5 + +if [[ "$1" = "shell" ]]; then + exec /bin/bash +fi + +cd /home/short-server +python3 server.py + diff --git a/server.py b/server.py new file mode 100755 index 0000000..9677b95 --- /dev/null +++ b/server.py @@ -0,0 +1,8 @@ +from app import app + +@app.shell_context_processor +def make_shell_context(): + return{'app': app, 'position': Position} + +if __name__ == '__main__': + app.run('0.0.0.0', 8088, debug=True)