Amos
Amos
Explore posts from servers
CDCloudflare Developers
Created by Amos on 12/5/2024 in #workers-help
Astro caching with output = server
I added
Astro.response.headers.set("Cache-Control", "public, s-maxage=60, stale-while-revalidate=30");
Astro.response.headers.set("Cache-Control", "public, s-maxage=60, stale-while-revalidate=30");
to one of my pages deployed with @astrojs/cloudflare and I do see the response header in my network tab, but it's seemingly not caching anything. I am displaying the current time and it changes every time I refresh the page. Shouldn't it cache the HTML for 60 seconds? Output is set to server and the page is just this
---
const currentTime = new Date().toLocaleTimeString();

Astro.response.headers.set('Cache-Control', 'public, s-maxage=60, stale-while-revalidate=30');
---

<html>
<head>
<title>Current Time</title>
</head>
<body>
<h1>The current time is: {currentTime}</h1>
</body>
</html>
---
const currentTime = new Date().toLocaleTimeString();

Astro.response.headers.set('Cache-Control', 'public, s-maxage=60, stale-while-revalidate=30');
---

<html>
<head>
<title>Current Time</title>
</head>
<body>
<h1>The current time is: {currentTime}</h1>
</body>
</html>
3 replies
CDCloudflare Developers
Created by Amos on 12/4/2024 in #workers-help
Rewriting subdomain.example.com to example.com/subdomain
I am deploying an Astro site with middleware and want to rewrite test.example.com to example.com/test, however it returns a 522 error.
import type { MiddlewareHandler } from "astro";

export const onRequest: MiddlewareHandler = async (context, next) => {
const { request, locals } = context;

// Skip non-GET requests or if the URL matches the skip pattern
if (request.method !== "GET") return next();

const SKIP_PATTERN = /^(?:\/_image\/|\/_astro\/|[/\w-]+\.[\w-]+$)/;
if (SKIP_PATTERN.test(context.url.pathname)) return next();

const frontendUrl = locals.runtime.env.FRONTEND_URL;
const host = context.url.host;

// Handle subdomain extraction
let subdomain: string | undefined = undefined;
if (host.endsWith(".localhost:1234")) {
const parts = host.replace(":1234", "").split(".");
subdomain = parts.length > 1 ? parts[0] : undefined;
} else if (host.endsWith(frontendUrl)) {
const parts = host.split(".");
subdomain = parts.length > 2 ? parts[0] : undefined;
}

console.log("Subdomain:", subdomain);

// If no subdomain, continue with the original request
if (!subdomain) return next();

// Rewrite the URL to include the subdomain path
const newUrl = `${context.url.protocol}//${frontendUrl}/${subdomain}${context.url.pathname}${context.url.search}`;
console.log("Rewriting to:", newUrl);

const response = await fetch(newUrl);
return response;
};
import type { MiddlewareHandler } from "astro";

export const onRequest: MiddlewareHandler = async (context, next) => {
const { request, locals } = context;

// Skip non-GET requests or if the URL matches the skip pattern
if (request.method !== "GET") return next();

const SKIP_PATTERN = /^(?:\/_image\/|\/_astro\/|[/\w-]+\.[\w-]+$)/;
if (SKIP_PATTERN.test(context.url.pathname)) return next();

const frontendUrl = locals.runtime.env.FRONTEND_URL;
const host = context.url.host;

// Handle subdomain extraction
let subdomain: string | undefined = undefined;
if (host.endsWith(".localhost:1234")) {
const parts = host.replace(":1234", "").split(".");
subdomain = parts.length > 1 ? parts[0] : undefined;
} else if (host.endsWith(frontendUrl)) {
const parts = host.split(".");
subdomain = parts.length > 2 ? parts[0] : undefined;
}

console.log("Subdomain:", subdomain);

// If no subdomain, continue with the original request
if (!subdomain) return next();

// Rewrite the URL to include the subdomain path
const newUrl = `${context.url.protocol}//${frontendUrl}/${subdomain}${context.url.pathname}${context.url.search}`;
console.log("Rewriting to:", newUrl);

const response = await fetch(newUrl);
return response;
};
I'm guessing it's getting stuck in a loop or something? Not sure how to handle this properly
6 replies
CDCloudflare Developers
Created by Amos on 11/3/2024 in #workers-help
React + Vite SPA
I have a simple React SPA with Vite. Wondering if I should use Pages or it's recommended to use workers for this as well? Couldn't find any examples in your docs (only for Remix, Next.js etc. not just a plain React SPA)
2 replies
CDCloudflare Developers
Created by Amos on 10/15/2024 in #general-help
403 when updating env variables
I'm trying to add env variables to a workers project through the dashboard and getting a 403 error
API Request Failed: POST /api/v4/accounts/.../workers/scripts/.../versions (403)
API Request Failed: POST /api/v4/accounts/.../workers/scripts/.../versions (403)
2 replies
CDCloudflare Developers
Created by Amos on 10/14/2024 in #workers-help
Astro Image component
I'm using the new experimental stuff and using Astro's Image component, but when I deploy the images don't work because it's a url like
/_image?href=%2F_astro%2Flogo-horizontal-black.BLA2JIcF.svg&f=svg
/_image?href=%2F_astro%2Flogo-horizontal-black.BLA2JIcF.svg&f=svg
which is giving error code: 1042
5 replies
CDCloudflare Developers
Created by Amos on 6/13/2024 in #general-help
Image transformations: 404 error
No description
10 replies
CDCloudflare Developers
Created by Amos on 3/13/2024 in #general-help
Bandwidth when transforming via URL
Deciding whether or not we should use Cloudflare for image transformations or host something like imgproxy ourselves. We already have the images on AWS, but it's not clear to me if there is no bandwidth used after the first time we load an S3 image proxied through Cloudflare. Both from S3 and Cloudflare
2 replies
DTDrizzle Team
Created by Amos on 3/5/2024 in #help
Using ATTACH with Drizzle
I want to use ATTACH with Drizzle so I can join between 2 dbs, is this currently possible? Something like this:
import { createClient } from "@libsql/client";

async function example() {
const db = createClient({
url: process.env.LIBSQL_URL,
authToken: process.env.LIBSQL_AUTH_TOKEN,
});
const txn = await db.transaction("read");
await txn.execute("ATTACH \"bc307076-d9fc-11ee-b5d4-f69bd26a54ba\" AS attached");
const rs = await txn.execute("SELECT * FROM attached.t");
console.log(rs);
txn.close();
}

await example();
import { createClient } from "@libsql/client";

async function example() {
const db = createClient({
url: process.env.LIBSQL_URL,
authToken: process.env.LIBSQL_AUTH_TOKEN,
});
const txn = await db.transaction("read");
await txn.execute("ATTACH \"bc307076-d9fc-11ee-b5d4-f69bd26a54ba\" AS attached");
const rs = await txn.execute("SELECT * FROM attached.t");
console.log(rs);
txn.close();
}

await example();
1 replies
TTCTheo's Typesafe Cult
Created by Amos on 11/24/2022 in #questions
Sentry with Next.js in an Nx monorepo?
Anyone got this up and running? Can't seem to figure it out
12 replies
TTCTheo's Typesafe Cult
Created by Amos on 11/8/2022 in #questions
Prisma and Stripe subscription authorisation
I am working on a side project that has different tiers of subscriptions. I'm using Stripe and have set up everything to sync up subscriptions, prices and products from Stripe with my database. Now depending on the tier of the subscription users have certain restrictions. For example (completely random), imagine restricting people to X blog posts, Y tweets per day or access to feature Z . Would you guys put this information on the metadata of the Stripe product like
{"blogLimit": 5, "tweetDailyLimit": 10, "featureYEnabled": true}
{"blogLimit": 5, "tweetDailyLimit": 10, "featureYEnabled": true}
or create a new table in your database like
model ProductConfiguration {
id String @id @default(cuid())
blogLimit Int
tweetDailyLimit Int
featureYEnabled Boolean

product Product @relation(fields: [productId], references: [id])
productId String @unique //
}
model ProductConfiguration {
id String @id @default(cuid())
blogLimit Int
tweetDailyLimit Int
featureYEnabled Boolean

product Product @relation(fields: [productId], references: [id])
productId String @unique //
}
The benefit to the metadata is you can directly edit it from Stripe, while the benefit of the table is that you actually know what it contains. Thoughts? How do you guys handle this stuff?
4 replies