initial commit, adding flask structure, README, routes
- routes defined in routes.py uses the <path:..> function to catch every non-empty url comming along - request.full_path is used to get the entire url, as <path:> 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
This commit is contained in:
commit
85850a9d63
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
__pycache__/
|
16
README.md
Normal file
16
README.md
Normal file
@ -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
|
||||
|
8
app/__init__.py
Normal file
8
app/__init__.py
Normal file
@ -0,0 +1,8 @@
|
||||
from flask import Flask
|
||||
|
||||
|
||||
app = Flask(__name__,
|
||||
static_folder='static',
|
||||
template_folder='template')
|
||||
|
||||
from app import routes
|
42
app/routes.py
Normal file
42
app/routes.py
Normal file
@ -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/<path:short>", 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("/<path:path>", 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
|
||||
|
||||
|
10
app/static/css/style.css
Normal file
10
app/static/css/style.css
Normal file
@ -0,0 +1,10 @@
|
||||
html
|
||||
{
|
||||
font-family: Segoe UI, Frutiger, sans-serif;
|
||||
width: 100%; height: 100%
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0px;
|
||||
}
|
||||
|
BIN
app/static/res/favicon.ico
Normal file
BIN
app/static/res/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
1
app/static/res/short.json
Normal file
1
app/static/res/short.json
Normal file
@ -0,0 +1 @@
|
||||
[]
|
18
app/template/short.html
Normal file
18
app/template/short.html
Normal file
@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8", content="width=device-width", name="viewport"/>
|
||||
<title>Link Shortening</title>
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style.css') }}">
|
||||
<link rel="shortcut icon" type="image/jpg" href="{{ url_for('static', filename='res/favicon.ico') }}">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>
|
||||
Your Link:
|
||||
</h2>
|
||||
{{ path }}
|
||||
</body>
|
||||
|
||||
</html>
|
7
docker/README.md
Normal file
7
docker/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
## Goal
|
||||
|
||||
run short-server in a docker-compose environment
|
||||
|
||||
## Usage
|
||||
|
||||
1. `docker-compose up -d` starts the containers in background
|
28
docker/docker-compose.yml
Normal file
28
docker/docker-compose.yml
Normal file
@ -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
|
8
docker/short-server/Dockerfile
Normal file
8
docker/short-server/Dockerfile
Normal file
@ -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"]
|
12
docker/short-server/docker-entrypoint.sh
Executable file
12
docker/short-server/docker-entrypoint.sh
Executable file
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user