Compare commits

...

4 Commits

Author SHA1 Message Date
meeg_leeto b3f73fde50 feat: barebones HTML interface is working 2022-04-30 00:53:42 +01:00
meeg_leeto adb6853de5 refact: minor refactor 2022-04-30 00:22:47 +01:00
meeg_leeto 23c77c79f3 fix: try to serve anything that doesn't match from the dir 2022-04-30 00:20:44 +01:00
meeg_leeto f7297cdadd chore: use regular BASE64 instead
From the javascript side, using non-standard base64 was more trouble
than it's worth.
2022-04-30 00:19:57 +01:00
3 changed files with 90 additions and 32 deletions

View File

@ -1,13 +1,30 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<title>Lonk</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<link rel='stylesheet' type='text/css' media='screen' href='main.css'>
<script src="main.js"></script>
</head>
<body>
<h1 id="shortened"></h1>
<!-- Yes, this form requires Javascript, sorry.
I promise there are no trackers on this page,
but if you're tech savvy (and paranoid) enough to
be browsing the web with Javascript blocked, then
just do a POST request to /shorten with the URL you
wish to shorten Base64-encoded as the body. -->
<form id="form">
<input type="url" name="url" id="url" required>
<input type="submit" hidden />
</form>
<p id="info"></p>
</body>
</html>

56
data/served/main.js Normal file
View File

@ -0,0 +1,56 @@
'use strict';
(() => {
document.addEventListener('DOMContentLoaded', (_) => {
const waiting = false;
let xhr;
const field = document.getElementById('url');
field.addEventListener('change', () => {
if (waiting && xhr != null) {
xhr.abort();
}
});
const form = document.getElementById('form');
form.addEventListener('submit', (event) => {
// We need to create a different body, so prevent the default submission.
event.preventDefault();
if (waiting) {
// Prevent multiple requests.
return;
}
// Get the URL the user is trying to shorten.
const url = document.getElementById('url').value;
// Encode the URL as Base64.
const encoded = btoa(encodeURIComponent(url).replace(/%([0-9A-F]{2})/g, (match, p1) =>
String.fromCharCode('0x' + p1)
));
// POST the body to /shorten.
xhr = new XMLHttpRequest();
xhr.open('POST', '/shorten', true);
xhr.overrideMimeType('text/plain');
xhr.send(encoded);
xhr.onload = () => {
switch (xhr.status) {
case 200:
let slug = xhr.response;
console.log(slug);
break;
default:
console.log(xhr.response);
break;
}
};
xhr.onerror = () => {
// TODO
};
});
});
})();

View File

@ -6,19 +6,6 @@ use warp::{http::Response, hyper::StatusCode, Filter};
#[macro_use]
/// Module containing custom defined macros.
mod macros {
macro_rules! clone {
(mut $y:ident) => {
let mut $y = $y.clone();
};
($y:ident) => {
let $y = $y.clone();
};
($y:ident, $($x:ident),+) => {
clone!($y);
clone!($($x),+);
};
}
/// Macros useful for debug contexts.
///
/// For example, `ifdbg!(expr)` replaces the $expr with () when the compile
@ -90,8 +77,6 @@ mod macros {
}
}
use macros::debug;
/// Affine to static configuration.
mod conf {
use serde::{Deserialize, Serialize};
@ -675,23 +660,21 @@ async fn shorten(
db: &db::SlugDatabase,
b64str: &str,
) -> Result<slug::Slug, (StatusCode, String)> {
// Parse the URL given by the user. It should arrive as a URL Base64
// no-padding string, and anything other than this should cleanly result in
// an HTTP rejection.
// Parse the URL given by the user. It should arrive as a Base64 string,
// and anything other than this should cleanly result in an HTTP rejection.
let url = {
let unencoded_bytes =
base64::decode_config(b64str, base64::URL_SAFE_NO_PAD).map_err(|_| {
(
warp::http::StatusCode::BAD_REQUEST,
debuginfo!("Could not decode base64 str.", "Invalid URL Base64.").into(),
)
})?;
let unencoded_bytes = base64::decode_config(b64str, base64::STANDARD).map_err(|_| {
(
warp::http::StatusCode::BAD_REQUEST,
debuginfo!("Could not decode base64 str.", "Invalid Base64.").into(),
)
})?;
let url_str = std::str::from_utf8(&unencoded_bytes[..]).map_err(|_| {
(
warp::http::StatusCode::BAD_REQUEST,
debuginfo!(
"Parsed bytes of base64 str, but could not decode as UTF8.",
"Invalid URL Base64."
"Invalid Base64."
)
.into(),
)
@ -822,10 +805,7 @@ async fn serve() {
let slug_factory: &'static slug::SlugFactory = Box::leak(Box::new(slug_factory));
let db: &'static db::SlugDatabase = Box::leak(Box::new(db));
// GET /
let homepage = warp::path::end().and(config.serve_rules.dir.to_filter());
// POST /shorten/ with argument link:Base64WithoutPaddingUrl
// POST /shorten/ with link in argument
let shorten = warp::post()
.and(warp::path("shorten"))
.and(warp::body::content_length_limit(1024))
@ -860,7 +840,12 @@ async fn serve() {
}
});
let get_routes = warp::get().and(homepage.or(link));
// GET /
// This should be the last thing matched, so that anything that doesn't
// match another filter will try to match a file.
let homepage = warp::get().and(config.serve_rules.dir.to_filter());
let get_routes = warp::get().and(link.or(homepage));
let post_routes = warp::post().and(shorten);
let routes = get_routes.or(post_routes);