Compare commits

..

No commits in common. "1424fb2f431f8bc0e7e98222f1df488b53782ffa" and "9ed16ac6cd11307034d76e6131df0d6beb547ecd" have entirely different histories.

8 changed files with 19 additions and 82 deletions

2
.gitignore vendored
View File

@ -1,5 +1,3 @@
/target /target
venv venv
__pycache__ __pycache__
/.env
/data/

View File

@ -1,18 +1,11 @@
# Use an official Python runtime as a parent image FROM python:3.11
FROM python:3
# Set the working directory in the container WORKDIR /code
WORKDIR /app
# Install any needed packages specified in requirements.txt COPY ./requirements.txt /code/requirements.txt
COPY requirements.txt /app/
RUN pip install --no-cache-dir -r requirements.txt
# Copy the current directory contents into the container at /app RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
COPY . /app/
# Make port 8000 available to the world outside this container COPY ./app /code/app
EXPOSE 8000
# Run api.py when the container launches CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
CMD ["uvicorn", "api:app", "--host", "0.0.0.0", "--port", "8000"]

7
api.py
View File

@ -16,13 +16,8 @@ async def root():
@app.get("/{url_id}", status_code=301, response_class=RedirectResponse) @app.get("/{url_id}", status_code=301, response_class=RedirectResponse)
async def redirect_urls(url_id): async def redirect_urls(url_id):
db = couch["urls"] target_url = couch["urls"][url_id].get('full_url')
if url_id in db:
target_url = db[url_id].get('full_url')
return RedirectResponse(target_url) return RedirectResponse(target_url)
else:
return RedirectResponse('static/404.html')
# TODO: Get JWT tokens working and use that to return only the user's urls # TODO: Get JWT tokens working and use that to return only the user's urls
# TODO: Look into how FastAPI handles the Authentication header # TODO: Look into how FastAPI handles the Authentication header

View File

@ -32,10 +32,6 @@ GET :host/eecd98
# Talk directly to CouchDB # Talk directly to CouchDB
### ###
# Get value from key
GET http://admin:password@127.0.0.1:5984/_all_dbs
:headers
# Get value from key # Get value from key
GET http://admin:password@127.0.0.1:5984/urls/_all_docs?include_docs=true GET http://admin:password@127.0.0.1:5984/urls/_all_docs?include_docs=true
:headers :headers

View File

@ -1,19 +0,0 @@
version: '3'
services:
couchdb:
image: couchdb:latest
network_mode: host
volumes:
- ./data:/opt/couchdb/data:Z
env_file:
- .env
fastapi_app:
build:
context: .
dockerfile: Dockerfile
network_mode: host
depends_on:
- couchdb
env_file:
- .env

View File

@ -2,10 +2,10 @@
#+TODO: TODO INPROGRESS | DONE BACKLOG #+TODO: TODO INPROGRESS | DONE BACKLOG
#+STARTUP: overview #+STARTUP: overview
* DONE Add button to copy shortened URL to clipboard * TODO Move everything into an app directory
* DONE Add a 404 page in case the URL provided is invalid * TODO Knock out source code TODOs
* TODO RTFM on how to create docker compose files * TODO Add button to copy shortened URL to clipboard
* TODO Containerize couchdb * TODO Add a 404 page in case the URL provided is invalid
* TODO Get the container running with the Dockerfile * TODO Get the container running with the Dockerfile
* TODO Point zipmy.link to joe-vps * TODO Point zipmy.link to joe-vps
- [ ] Add DNS records - [ ] Add DNS records
@ -14,6 +14,8 @@
* TODO Create a README.org * TODO Create a README.org
* TODO Add MIT license * TODO Add MIT license
* BACKLOG Containerize couchdb
* BACKLOG RTFM on how to create docker compose files
* BACKLOG RTFM on how to create a container network * BACKLOG RTFM on how to create a container network
* BACKLOG Gitea Actions * BACKLOG Gitea Actions
* BACKLOG Unit tests * BACKLOG Unit tests

View File

@ -1,15 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Zip My Link</title>
<link rel="stylesheet" href="main.css">
</head>
<body>
<h1>Zip My Link</h1>
<h1>404</h1>
<p>The shortened URL you provided was not found. Sorry about that!</p>
<a href="index.html">zipmy.link</a>
</body>
</html>

View File

@ -1,33 +1,20 @@
function copyUrlToClipboard() {
const urlInput = document.getElementById("url-input");
urlInput.select();
urlInput.setSelectionRange(0, 99999);
navigator.clipboard.writeText(urlInput.value);
}
function resetLinkGeneration() {
}
async function shortenUrl() { async function shortenUrl() {
const urlInput = document.getElementById("url-input"); const url = document.getElementById("url-input").value;
const btn = document.getElementById("submit-btn"); const btn = document.getElementById("submit-btn").value;
// btn.enab // btn.enab
const response = await fetch("/api/v1/urls", { const response = await fetch("/api/v1/urls", {
method: 'PUT', method: 'PUT',
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
body: JSON.stringify({ url: urlInput.value, username: "anonymous" }) body: JSON.stringify({ url: url, username: "anonymous" })
}); });
const data = await response.json(); const data = await response.json();
const resultElement = document.getElementById("result"); const resultElement = document.getElementById("result");
if (response.ok) { if (response.ok) {
resultElement.textContent = '' resultElement.textContent = `Shortened Url: ${data.shortenedUrl}`
urlInput.value = data.shortenedUrl; resultElement.style.color = "black";
btn.innerText = "📋 Copy to Clipboard!";
btn.onclick = copyUrlToClipboard;
} else { } else {
resultElement.textContent = `Error: ${data.detail}` resultElement.textContent = `Error: ${data.detail}`
resultElement.style.color = "red"; resultElement.style.color = "red";
btn.value = "Shorten Url";
} }
} }