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