From 9793a9acd9c3058dc96bd3b6281540fe7d02a7db Mon Sep 17 00:00:00 2001 From: Nikolay Bonev Date: Mon, 12 Aug 2024 16:32:26 +0300 Subject: [PATCH 1/3] added documentation and started working on adjustments --- docs/url-shortener.md | 11 +++++++++++ server/middleware.ts | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/docs/url-shortener.md b/docs/url-shortener.md index 6082a7f42..4339088b6 100644 --- a/docs/url-shortener.md +++ b/docs/url-shortener.md @@ -6,8 +6,19 @@ The url shortener functionality allows you to make your QR codes hold less data, thus making them more readable. The redirection is handled via the `urlShortener` middleware. +## How to use it? + Using the shortener is super easy. 1. Add an env variable with your shortner domain: `URL_SHORTENER="eam.sh"`. You can refer to `.env.example` for further example. The domain should not include the protocol (http/https) or a trailing slash 2. Make sure you point your short domain to your application server 3. Enjoy + +## How does it work? + +1. When a request is received starting with the shortened url, it gets handled by the `urlShortener` middleware +2. The following conditions need to be met for the middleware to redirect to a QR code. In the rest of the cases, it just redirects to app root. + - The path should NOT include any special characters + - The path should start with a small letter + - The path should only have small letters and optional number + - The path's length should fit within the allowed character lengths(10 for new and 25 for legacy QR codes) diff --git a/server/middleware.ts b/server/middleware.ts index 5a6a18e72..797321f59 100644 --- a/server/middleware.ts +++ b/server/middleware.ts @@ -164,6 +164,17 @@ export function urlShortener({ excludePaths }: { excludePaths: string[] }) { const path = pathParts.join("/"); const serverUrl = process.env.SERVER_URL; + /** + * The following conditions need to be met for the middleware to redirect to a QR code. In the rest of the cases, it just redirects to app root. + * - The path should NOT include any special characters + * - The path should start with a small letter + * - The path should only have small letters and optional number + * - The path's length should fit within the allowed character lengths(10 for new and 25 for legacy QR codes) + */ + + console.log(`urlShortener middleware: Processing ${path}`); + return next(); + // Check if the path is a single segment and a valid CUID if (pathParts.length === 1 && isQrId(path)) { const redirectUrl = `${serverUrl}/qr/${path}`; From 54c232010bf424ba8723bb32a56db7657452a767 Mon Sep 17 00:00:00 2001 From: Donkoko Date: Mon, 12 Aug 2024 17:05:05 +0300 Subject: [PATCH 2/3] adjusting logic in middleware to redirect to qr if valid or if not, to the app root --- app/utils/id/index.ts | 18 ++++++------------ server/middleware.ts | 22 +++++++--------------- 2 files changed, 13 insertions(+), 27 deletions(-) diff --git a/app/utils/id/index.ts b/app/utils/id/index.ts index 6f6b4cc36..cea86e1fc 100644 --- a/app/utils/id/index.ts +++ b/app/utils/id/index.ts @@ -10,20 +10,14 @@ export function isQrId(id: string): boolean { const possibleLengths = [DEFAULT_CUID_LENGTH, LEGACY_CUID_LENGTH]; const length = id.length; - // @TODO - temporary disabled number check due to bug and corrupted ids - // /** - // * 1. The string must contain only lowercase letters and digits. - // * 2. The string must start with a lowercase letter. - // * 3. The string must contain at least one digit. - // */ - // const regex = /^(?=.*\d)[a-z][0-9a-z]*$/; - /** - * Adjusted criteria: - * 1. The string must contain only lowercase letters. - * 2. The string must start with a lowercase letter. + * The following conditions need to be met for the middleware to redirect to a QR code. In the rest of the cases, it just redirects to app root. + * - The path should NOT include any special characters + * - The path should start with a small letter + * - The path should only have small letters and optional number + * - The path's length should fit within the allowed character lengths(10 for new and 25 for legacy QR codes) */ - const regex = /^[a-z][0-9a-z]*$/; + const regex = /^[a-z][a-z0-9]*$/; // Validate the ID against the criteria if ( diff --git a/server/middleware.ts b/server/middleware.ts index 797321f59..2cb60675d 100644 --- a/server/middleware.ts +++ b/server/middleware.ts @@ -142,6 +142,7 @@ export function cache(seconds: number) { export function urlShortener({ excludePaths }: { excludePaths: string[] }) { return createMiddleware(async (c, next) => { const fullPath = c.req.path; + // Remove the URL_SHORTENER part from the beginning of the path const pathWithoutShortener = fullPath.replace( `/${process.env.URL_SHORTENER}`, @@ -164,17 +165,6 @@ export function urlShortener({ excludePaths }: { excludePaths: string[] }) { const path = pathParts.join("/"); const serverUrl = process.env.SERVER_URL; - /** - * The following conditions need to be met for the middleware to redirect to a QR code. In the rest of the cases, it just redirects to app root. - * - The path should NOT include any special characters - * - The path should start with a small letter - * - The path should only have small letters and optional number - * - The path's length should fit within the allowed character lengths(10 for new and 25 for legacy QR codes) - */ - - console.log(`urlShortener middleware: Processing ${path}`); - return next(); - // Check if the path is a single segment and a valid CUID if (pathParts.length === 1 && isQrId(path)) { const redirectUrl = `${serverUrl}/qr/${path}`; @@ -182,9 +172,11 @@ export function urlShortener({ excludePaths }: { excludePaths: string[] }) { return c.redirect(safeRedirect(redirectUrl), 301); } - // Handle all other cases - const redirectUrl = `${serverUrl}${pathname}`; - // console.log(`urlShortener middleware: Redirecting to ${redirectUrl}`); - return c.redirect(safeRedirect(redirectUrl), 301); + // console.log(`urlShortener middleware: Redirecting to ${serverUrl}`); + /** + * In all other cases, we just redirect to the app root. + * The URL shortener should only be used for QR codes + * */ + return c.redirect(safeRedirect(serverUrl), 301); }); } From 19e6a9315c0be714417caa2dbbc3023ffbcade7b Mon Sep 17 00:00:00 2001 From: Donkoko Date: Mon, 12 Aug 2024 17:33:08 +0300 Subject: [PATCH 3/3] adjusted regex of scanner --- app/components/zxing-scanner.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/app/components/zxing-scanner.tsx b/app/components/zxing-scanner.tsx index b20c65c91..bcbf7dffe 100644 --- a/app/components/zxing-scanner.tsx +++ b/app/components/zxing-scanner.tsx @@ -32,6 +32,7 @@ export const ZXingScanner = ({ * - ^(https?:\/\/[^\/]+\/ matches the protocol, domain, and the initial slash. * - (?:qr\/)? optionally matches the /qr/ part. * - ([a-zA-Z0-9]+))$ matches the QR ID which is the last segment of the URL. + * - $ ensures that there are no additional parts after the QR ID. */ // Regex to match both old and new QR code structures const regex = /^(https?:\/\/[^/]+\/(?:qr\/)?([a-zA-Z0-9]+))$/;