Introduction
In order to use a domain name which was unused, I developed a web service of URL shortener by myself.
Choosing Cloud Providers and its Services
The service candidates for use include container-based service or serverless computing services. URL shortener service has a simple processing logic and doesn't require storing data as in-memory data. Therefore, serverless computing services are chosen.
I have experience for using public cloud services such as AWS, GCP, and Azure. In contrast, I have no experience for using the web services which is provided by Cloudflare. Therefore, this project uses Cloudflare Workers as the service platform.
The requirement for this project is to store URL on databases. Cloudflare provides Cloudflare Workers KV as key-value pair store. These services are provided as a free tier service.
System Architecture
Clients
|
v
+-----------------+ +--------------------+
|Cloudflare Worker| --> |Cloudflare Worker KV|
+-----------------+ +--------------------+
Codes
Following codes are deployed on Cloudflare Workers as a function. Then, you create a key-value store on Cloudflare Workers KV, and this is named as MY_KV
.
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
if (request.method === "GET") {
return readRedirect(request)
} else if (request.method === "POST") {
return createRedirect(request)
} else {
return new Response("Forbidden", { status: 403 })
}
};
async function readRedirect(request) {
const url = new URL(request.url);
const req_path = url.pathname;
const value = await MY_KV.get(req_path);
if (value === null) {
console.log("Not Found", req_path);
return new Response("Not Found", { status: 404 });
}
console.log("Redirect", req_path);
const statusCode = 301;
return Response.redirect(value, statusCode);
};
async function createRedirect(request) {
const url = new URL(request.url);
const req_path = url.pathname;
const secret_token = "xxxxx-xxxxxx-xxxxxx-xxxxxx";
if (req_path !== "/token/" + secret_token) {
return new Response("Invalid Token", { status: 401 });
}
const content_type = request.headers.get("content-type");
if (!content_type.includes("application/json")) {
return new Response("Invalid Content Type", { status: 400 });
}
const request_body = await request.json();
const redirect_from_path = request_body["from_path"]; // "/foo"
const redirect_to_url = request_body["to_url"]; // http://example.com
await MY_KV.put(redirect_from_path, redirect_to_url);
return new Response("https://1ch.dev" + redirect_from_path);
};
Usage
iOS Shortcuts
CLI commands
This code is supported for .zshrc
.
function tiny() {
read to_url
echo $to_url | grep 'http\(s\)\?://' || {
echo "Invalid URL"
return 1
}
from_path="/cli-$(date +%s)"
curl -XPOST -H 'Content-Type: application/json' \
-d "{\"from_path\": \"$from_path\", \"to_url\": \"$to_url\"}" \
https://1ch-dev.xxxxxxxx.workers.dev/token/xxxxxxxx \
| pbcopy
}
Usage:
echo "http://example.com/" | tiny
Top comments (0)