···5050 <InBetweenCTA
5151 description="Learn over time how your services are performing, and inform your users when there are issues."
5252 actions={{
5353- primary: { label: "Start for Free", href: "/app/sign-up" },
5353+ primary: { label: "Start for Free", href: "/app/login" },
5454 secondary: { label: "Schedule a Demo", href: "/cal", target: "_blank" },
5555 }}
5656 />
···11+export * from "./parser/cache-control";
22+export * from "./parser/cf-cache-status";
33+export * from "./parser/cf-ray";
44+export * from "./parser/fly-request-id";
55+export * from "./parser/x-vercel-cache";
66+export * from "./parser/x-vercel-id";
···11+interface CacheControlInfo {
22+ directive: string; // unparsed directive
33+ description: string;
44+ name: string;
55+ value?: number;
66+}
77+88+export function parseCacheControlHeader(header: string): CacheControlInfo[] {
99+ const cacheControlDirectives = header
1010+ .split(",")
1111+ .map((directive) => directive.trim());
1212+1313+ const cacheControlInfo: CacheControlInfo[] = [];
1414+1515+ cacheControlDirectives.forEach((directive) => {
1616+ const parts = directive.split("=");
1717+1818+ const name = parts[0].trim();
1919+ const value = !isNaN(Number(parts[1])) ? Number(parts[1]) : undefined;
2020+ const description = getDirectiveDescription(name);
2121+2222+ cacheControlInfo.push({ description, name, value, directive });
2323+ });
2424+2525+ return cacheControlInfo;
2626+}
2727+2828+function getDirectiveDescription(key: string): string {
2929+ switch (key.toLowerCase()) {
3030+ case "max-age":
3131+ return "Specifies the maximum amount of time in seconds that a resource is considered fresh in a cache. After this time, the cache is required to revalidate the resource with the origin server.";
3232+ case "max-stale":
3333+ return "Indicates that a cache can serve a stale response even after its freshness lifetime has expired. Optionally, a value can be specified to indicate the maximum staleness allowed.";
3434+ case "min-fresh":
3535+ return "Specifies the minimum amount of time in seconds that a resource must be considered fresh. Caches should not serve a response that is older than this value without revalidating with the origin server.";
3636+ case "s-maxage":
3737+ return "Similar to max-age, but applies specifically to shared caches, such as proxy servers. Overrides max-age when present in shared caches.";
3838+ case "no-cache":
3939+ return "Forces caches to submit the request to the origin server for validation before releasing a cached copy. The response must be validated with the origin server before it can be used.";
4040+ case "no-store":
4141+ return "Instructs caches not to store any part of either the request or response. The content must be obtained from the origin server for each request.";
4242+ case "no-transform":
4343+ return "Specifies that intermediaries should not modify the content of the resource, such as by transcoding or compressing it.";
4444+ case "only-if-cached":
4545+ return "Indicates that a cache should respond only if the resource is available in the cache. It should not contact the origin server to retrieve the resource.";
4646+ case "must-revalidate":
4747+ return "Specifies that caches must revalidate stale responses with the origin server before using them.";
4848+ case "proxy-revalidate":
4949+ return "Similar to must-revalidate, but applies specifically to shared caches. It indicates that shared caches must revalidate stale responses with the origin server before using them.";
5050+ case "private":
5151+ return "Indicates that the response is intended for a single user and should not be cached by shared caches.";
5252+ case "public":
5353+ return "Specifies that the response may be cached by any cache, including both private and shared caches.";
5454+ case "immutable":
5555+ return "Indicates that the response body will not change over time. Caches can store immutable responses indefinitely.";
5656+ case "stale-while-revalidate":
5757+ return "Allows a cache to serve stale responses while asynchronously revalidating them with the origin server in the background.";
5858+ case "stale-if-error":
5959+ return "Allows a cache to serve stale responses if the origin server is unavailable or returns an error.";
6060+ default:
6161+ return "";
6262+ }
6363+}
···11+interface CfCacheStatusInfo {
22+ description: string;
33+ value: string;
44+}
55+66+export function parseCfCacheStatus(header: string): CfCacheStatusInfo {
77+ const description = getCacheDescription(header);
88+ return { description, value: header };
99+}
1010+1111+function getCacheDescription(key: string): string {
1212+ switch (key.toUpperCase()) {
1313+ case "HIT":
1414+ return "Your resource was found in Cloudflare’s cache. This means that it has been previously accessed from your original server and loaded into Cache. It has not expired.";
1515+ case "MISS":
1616+ return "Cloudflare looked for your resource in cache but did not find it. Cloudflare went back to your origin server to retrieve the resource. The next time this resource is accessed its status should be HIT.";
1717+ case "BYPASS":
1818+ return "Cloudflare has been instructed to not cache this asset. It has been served directly from the origin. This is usually because something like an existing NO-CACHE header is being respected.";
1919+ case "EXPIRED":
2020+ return "Cloudflare has previously retrieved this resource, but its cache has expired. Cloudflare will go back to the origin to retrieve this resource again. The next time this resource is accessed its status should be HIT.";
2121+ case "DYNAMIC":
2222+ return "This resource is not cached by default and there are no explicit settings configured to cache it. You will see this frequently when Cloudflare is handling a POST request. This request will always go to the origin.";
2323+ default:
2424+ return "";
2525+ }
2626+}
+22
packages/header-analysis/src/parser/cf-ray.ts
···11+// List of all Cloudflare data center taken by https://www.feitsui.com/en/article/26
22+import { regions } from "../regions/cloudflare";
33+import type { ParserReturn, Region } from "../types";
44+55+export function parseCfRay(header: string): ParserReturn<Region> {
66+ const regex = /\b([A-Z]{3})\b/g;
77+ const arr = header.match(regex);
88+99+ if (!arr || !Array.isArray(arr) || arr.length === 0) {
1010+ return { status: "failed", error: new Error("Couldn't parse the header.") };
1111+ }
1212+1313+ const region = regions[arr[0]];
1414+ if (region) return { status: "success", data: region };
1515+1616+ return {
1717+ status: "failed",
1818+ error: new Error(
1919+ `It seems like the data center '${arr[0]}' (iata) is not listed.`,
2020+ ),
2121+ };
2222+}
···11+import { regions } from "../regions/fly";
22+import type { ParserReturn, Region } from "../types";
33+44+export function parseFlyRequestId(header: string): ParserReturn<Region> {
55+ const regex = /\b([a-z]{3})\b/g;
66+ const arr = header.match(regex);
77+88+ if (!arr || arr.length === 0) {
99+ return { status: "failed", error: new Error("Couldn't parse the header.") };
1010+ }
1111+1212+ const region = regions[arr[0]];
1313+ if (region) return { status: "success", data: region };
1414+1515+ return {
1616+ status: "failed",
1717+ error: new Error(
1818+ `It seems like the data center '${arr[0]}' (iata) is not listed.`,
1919+ ),
2020+ };
2121+}
···11+interface VercelCacheInfo {
22+ description: string;
33+ value: string;
44+}
55+66+export function parseXVercelCache(header: string): VercelCacheInfo {
77+ const description = getCacheDescription(header);
88+ return { description, value: header };
99+}
1010+1111+function getCacheDescription(key: string): string {
1212+ switch (key.toUpperCase()) {
1313+ case "MISS":
1414+ return "The response was not found in the edge cache and was fetched from the origin server.";
1515+ case "HIT":
1616+ return "The response was served from the edge cache.";
1717+ case "STALE":
1818+ return "The response was served from the edge cache. A background request to the origin server was made to update the content.";
1919+ case "PRERENDER":
2020+ return "The response was served from static storage.";
2121+ case "REVLIDATED":
2222+ return "The response was served from the origin server and the cache was refreshed due to an authorization from the user in the incoming request.";
2323+ default:
2424+ return "";
2525+ }
2626+}