Browse Source

refactor: getHost

Alexandru Cambose 3 months ago
parent
commit
18dd72e8e7

+ 11 - 5
apps/insights/src/server/pyth.ts

@@ -3,15 +3,16 @@ import { z } from "zod";
 
 import { VERCEL_REQUEST_HEADERS } from "../config/server";
 import { Cluster, ClusterToName, priceFeedsSchema } from "../services/pyth";
-import { absoluteUrl } from "../utils/absolute-url";
 import { DEFAULT_CACHE_TTL } from "../utils/cache";
+import { getHost } from "../utils/get-host";
 
 export async function getPublishersForFeedRequest(
   cluster: Cluster,
   symbol: string,
 ) {
-  const url = await absoluteUrl(
+  const url = new URL(
     `/api/pyth/get-publishers/${encodeURIComponent(symbol)}`,
+    await getHost(),
   );
   url.searchParams.set("cluster", ClusterToName[cluster]);
 
@@ -29,8 +30,9 @@ export async function getFeedsForPublisherRequest(
   cluster: Cluster,
   publisher: string,
 ) {
-  const url = await absoluteUrl(
+  const url = new URL(
     `/api/pyth/get-feeds-for-publisher/${encodeURIComponent(publisher)}`,
+    await getHost(),
   );
   url.searchParams.set("cluster", ClusterToName[cluster]);
 
@@ -46,7 +48,10 @@ export async function getFeedsForPublisherRequest(
 }
 
 export const getFeedsRequest = async (cluster: Cluster) => {
-  const url = await absoluteUrl(`/api/pyth/get-feeds`);
+  const url = new URL(
+    `/api/pyth/get-feeds`,
+    await getHost(),
+  );
   url.searchParams.set("cluster", ClusterToName[cluster]);
   url.searchParams.set("excludePriceComponents", "true");
 
@@ -72,8 +77,9 @@ export const getFeedForSymbolRequest = async ({
   symbol: string;
   cluster?: Cluster;
 }): Promise<z.infer<typeof priceFeedsSchema.element> | undefined> => {
-  const url = await absoluteUrl(
+  const url = new URL(
     `/api/pyth/get-feeds/${encodeURIComponent(symbol)}`,
+    await getHost(),
   );
   url.searchParams.set("cluster", ClusterToName[cluster]);
 

+ 0 - 36
apps/insights/src/utils/absolute-url.ts

@@ -1,36 +0,0 @@
-import { headers } from "next/headers";
-
-/**
- * Returns an absolute URL for the given pathname.
- *
- * @param pathname - The pathname to make absolute.
- * @returns A URL object with the absolute URL.
- */
-export async function absoluteUrl(pathname: string) {
-  let origin: string | undefined;
-
-  try {
-    // note that using headers() makes the context dynamic (disables full static optimization)
-    const nextHeaders = await headers();
-    // this can be comma-separated, so we take the first one
-    const xfHost = nextHeaders.get("x-forwarded-host")?.split(",")[0]?.trim();
-    const host = xfHost ?? nextHeaders.get("host") ?? undefined;
-
-    // this can be comma-separated, so we take the first one
-    const proto =
-      nextHeaders.get("x-forwarded-proto")?.split(",")[0]?.trim() ??
-      (host?.startsWith("localhost") ? "http" : "https");
-
-    // if we have a host and a proto, we can construct the origin
-    if (host && proto) origin = `${proto}://${host}`;
-  } catch {
-    throw new Error("Headers are not available in this context. Please check where are you calling this function from.");
-  }
-
-  if (!origin) {
-    throw new Error("No origin found! This should never happen.");
-  }
-
-  const path = pathname.startsWith("/") ? pathname : `/${pathname}`;
-  return new URL(origin + path);
-}

+ 28 - 0
apps/insights/src/utils/get-host.ts

@@ -0,0 +1,28 @@
+import { headers } from "next/headers";
+
+/**
+ * Returns the host of the current request.
+ *
+ * @returns The host of the current request.
+ */
+export const getHost = async () => {
+  const nextHeaders = await headers();
+  const xfHost = nextHeaders.get("x-forwarded-host")?.split(",")[0]?.trim();
+  const host = xfHost ?? nextHeaders.get("host") ?? undefined;
+  if (host === undefined) {
+    throw new NoHostError();
+  } else {
+    const proto =
+      nextHeaders.get("x-forwarded-proto")?.split(",")[0]?.trim() ??
+      (host.startsWith("localhost") ? "http" : "https");
+
+    return `${proto}://${host}`;
+  }
+}
+
+class NoHostError extends Error {
+  constructor() {
+    super("Request had neither an `x-forwarded-host` header nor a `host` header");
+    this.name = "NoHostError";
+  }
+}