Initial
This commit is contained in:
commit
be2ef06374
17
.gitignore
vendored
Normal file
17
.gitignore
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
/target
|
||||||
|
/dist
|
||||||
|
**/*.rs.bk
|
||||||
|
Cargo.lock
|
||||||
|
bin/
|
||||||
|
pkg/
|
||||||
|
wasm-pack.log
|
||||||
|
worker/
|
||||||
|
node_modules/
|
||||||
|
.cargo-ok
|
||||||
|
/__target__
|
||||||
|
/env
|
||||||
|
/.dev.vars
|
||||||
|
/.editorconfig
|
||||||
|
/.prettierrc
|
||||||
|
/.wrangler/
|
||||||
|
package-lock.json
|
12
package.json
Normal file
12
package.json
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"name": "linkie",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"deploy": "wrangler deploy",
|
||||||
|
"start": "wrangler dev"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"wrangler": "^3.0.0"
|
||||||
|
}
|
||||||
|
}
|
97
src/index.js
Normal file
97
src/index.js
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
// vim: tabstop=4 shiftwidth=4 expandtab
|
||||||
|
|
||||||
|
function makeid(length) {
|
||||||
|
let result = '';
|
||||||
|
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
|
||||||
|
const charactersLength = characters.length;
|
||||||
|
let counter = 0;
|
||||||
|
while (counter < length) {
|
||||||
|
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||||
|
counter += 1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkAuth(request) {
|
||||||
|
const auth = request.headers.get("Authorization");
|
||||||
|
return auth === AUTH_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getHost(request) {
|
||||||
|
return request.headers.get("Host")
|
||||||
|
}
|
||||||
|
|
||||||
|
async function add(host,path,request) {
|
||||||
|
if (!request.headers.get("content-type"))
|
||||||
|
return new Response("No URL provided", {status:400})
|
||||||
|
const data = await request.formData()
|
||||||
|
const dest = data.get("u")
|
||||||
|
if (!dest) return new Response("No URL provided",{status:400})
|
||||||
|
try {
|
||||||
|
new URL(dest)
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof TypeError)
|
||||||
|
return new Response("No valid URL provided",{status:400});
|
||||||
|
else throw e;
|
||||||
|
};
|
||||||
|
if (!path) return new Response("No path provided",{status:400})
|
||||||
|
if (path === "_") {
|
||||||
|
var x = 0
|
||||||
|
while (true) {
|
||||||
|
path = makeid(4)
|
||||||
|
const lookup = await KV.get(path)
|
||||||
|
if (!lookup) break
|
||||||
|
if (x >= 5) return new Response("Failed to generate a unique ID in 5 attempts", {status:500});
|
||||||
|
x += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await KV.put(path, dest)
|
||||||
|
return new Response(`https://${host}/${path}`, {status:201})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function remove(host,path) {
|
||||||
|
if (!path) return new Response("No path provided",{status:400})
|
||||||
|
await KV.delete(path)
|
||||||
|
return new Response(`DELETE https://${host}/${path}`, {status:200})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function get(host,path,auth) {
|
||||||
|
if (!path && auth) {
|
||||||
|
const { keys } = await KV.list()
|
||||||
|
let paths = ""
|
||||||
|
keys.forEach(element => paths += `${element.name}\n`);
|
||||||
|
return new Response(paths,{status:200})
|
||||||
|
}
|
||||||
|
if (!path) return Response.redirect("https://aly-smith.carrd.co",301)
|
||||||
|
const dest = await KV.get(path)
|
||||||
|
if (dest) return Response.redirect(dest, 302)
|
||||||
|
return new Response("Path not found", {status:404})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleRequest(request) {
|
||||||
|
const host = getHost(request)
|
||||||
|
const url = new URL(request.url)
|
||||||
|
var path = url.pathname.split("/")[1]
|
||||||
|
switch (request.method) {
|
||||||
|
case "PUT":
|
||||||
|
case "POST":
|
||||||
|
case "PATCH":
|
||||||
|
if (!checkAuth(request))
|
||||||
|
return new Response("Only GET requests allowed to unauthed users", {status:403});
|
||||||
|
return add(host,path,request)
|
||||||
|
case "DELETE":
|
||||||
|
if (!checkAuth(request))
|
||||||
|
return new Response("Only GET requests allowed to unauthed users", {status:403});
|
||||||
|
return remove(host,path)
|
||||||
|
case "HEAD":
|
||||||
|
case "GET":
|
||||||
|
return get(host,path,checkAuth(request))
|
||||||
|
default:
|
||||||
|
return new Response("Method not allowed", {status:405})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addEventListener('fetch', event => {
|
||||||
|
const { request } = event;
|
||||||
|
return event.respondWith(handleRequest(request));
|
||||||
|
});
|
77
test.py
Normal file
77
test.py
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
from requests import get,put,post,delete,patch,request
|
||||||
|
from os import environ
|
||||||
|
|
||||||
|
host = environ.get("HOST", "https://linkie.alyssa-dev-smith.workers.dev")
|
||||||
|
auth = {"Authorization": environ.get("AUTH", "")}
|
||||||
|
path = environ.get("TEST_PATH", "/devtestpath")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# unauth get /
|
||||||
|
req = get(host, allow_redirects=False)
|
||||||
|
assert req.status_code == 301 and "http" in req.headers["location"] # unauth get /
|
||||||
|
|
||||||
|
# auth get /
|
||||||
|
req = get(host,headers=auth)
|
||||||
|
assert req.status_code == 200 # auth get /
|
||||||
|
|
||||||
|
# unsupported method
|
||||||
|
req = request("OPTIONS", host)
|
||||||
|
assert req.status_code == 405 # unsupported method
|
||||||
|
|
||||||
|
# unauth requests to auth methods
|
||||||
|
reqs = put(host),post(host),delete(host)
|
||||||
|
assert all(req.status_code == 403 for req in reqs) # unauth requests to auth methods
|
||||||
|
|
||||||
|
# auth put wo data
|
||||||
|
req = put(host + path,data={},headers=auth)
|
||||||
|
assert req.status_code == 400 # auth put wo data
|
||||||
|
req = post(host + path,data={},headers=auth)
|
||||||
|
assert req.status_code == 400 # auth post wo data
|
||||||
|
req = patch(host + path,data={},headers=auth)
|
||||||
|
assert req.status_code == 400 # auth patch wo data
|
||||||
|
|
||||||
|
# auth put invalid url
|
||||||
|
req = put(host + path,data={"u": "golf sale"},headers=auth)
|
||||||
|
assert req.status_code == 400 # auth put invalid url
|
||||||
|
req = post(host + path,data={"u": "golf sale"},headers=auth)
|
||||||
|
assert req.status_code == 400 # auth post invalid url
|
||||||
|
req = patch(host + path,data={"u": "golf sale"},headers=auth)
|
||||||
|
assert req.status_code == 400 # auth patch invalid url
|
||||||
|
|
||||||
|
# auth put wo path
|
||||||
|
req = put(host,data={"u": "http://www.example.com"},headers=auth)
|
||||||
|
assert req.status_code == 400 # auth put wo path
|
||||||
|
req = post(host,data={"u": "http://www.example.com"},headers=auth)
|
||||||
|
assert req.status_code == 400 # auth post wo path
|
||||||
|
req = post(host,data={"u": "http://www.example.com"},headers=auth)
|
||||||
|
assert req.status_code == 400 # auth patch wo path
|
||||||
|
|
||||||
|
# auth put valid
|
||||||
|
req = put(host + path,data={"u": "http://www.example.com/?put"},headers=auth)
|
||||||
|
assert req.status_code == 201 # auth put valid
|
||||||
|
req = get(host + path, allow_redirects=False)
|
||||||
|
assert req.status_code == 302 and req.headers["location"] == "http://www.example.com/?put"
|
||||||
|
|
||||||
|
req = post(host + path + "post",data={"u": "http://www.example.com/?post"},headers=auth)
|
||||||
|
assert req.status_code == 201 # auth post valid
|
||||||
|
req = get(host + path + "post", allow_redirects=False)
|
||||||
|
assert req.status_code == 302 and req.headers["location"] == "http://www.example.com/?post"
|
||||||
|
|
||||||
|
req = patch(host + path + "patch",data={"u": "http://www.example.com/?patch"},headers=auth)
|
||||||
|
assert req.status_code == 201 # auth patch valid
|
||||||
|
req = get(host + path + "patch", allow_redirects=False)
|
||||||
|
assert req.status_code == 302 and req.headers["location"] == "http://www.example.com/?patch"
|
||||||
|
|
||||||
|
# auth delete wo path
|
||||||
|
req = delete(host,headers=auth)
|
||||||
|
assert req.status_code == 400 # auth delete wo path
|
||||||
|
|
||||||
|
# auth delete valid
|
||||||
|
req = delete(host + path,headers=auth)
|
||||||
|
assert req.status_code == 200 # auth delete valid
|
||||||
|
# req = get(host + path, allow_redirects=False)
|
||||||
|
# assert req.status_code == 404
|
||||||
|
except AssertionError:
|
||||||
|
print(req,req.headers,req.text)
|
||||||
|
raise
|
6
wrangler.toml
Normal file
6
wrangler.toml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
name = "linkie"
|
||||||
|
main = "src/index.js"
|
||||||
|
compatibility_date = "2023-09-14"
|
||||||
|
kv_namespaces = [
|
||||||
|
{ binding = "KV", id = "7214e776a3da4ccd9f9fe5b6c3d3f781" }
|
||||||
|
]
|
Loading…
Reference in a new issue