From 31c59c72931209cffe19dfa4cd11e5acb7940e75 Mon Sep 17 00:00:00 2001 From: Bret Little Date: Fri, 18 Nov 2022 15:36:19 -0500 Subject: [PATCH] Add proxy example --- packages/hydrogen-remix/src/index.ts | 1 + packages/hydrogen-remix/src/routing/proxy.ts | 49 +++++++++++++++++++ templates/demo-store/app/entry.server.tsx | 5 -- .../demo-store/app/hooks/useDeferred.tsx | 2 +- templates/demo-store/app/root.tsx | 8 +-- templates/demo-store/oxygen.ts | 16 +++++- 6 files changed, 70 insertions(+), 11 deletions(-) create mode 100644 packages/hydrogen-remix/src/routing/proxy.ts diff --git a/packages/hydrogen-remix/src/index.ts b/packages/hydrogen-remix/src/index.ts index 0ee86eeae8..7827eabaa0 100644 --- a/packages/hydrogen-remix/src/index.ts +++ b/packages/hydrogen-remix/src/index.ts @@ -8,6 +8,7 @@ export * from '@shopify/hydrogen'; export {RESOURCE_TYPES, REQUIRED_RESOURCES} from './routing/types'; export {notFoundMaybeRedirect} from './routing/redirect'; +export {proxyLiquidRoute} from './routing/proxy'; export type LoaderArgs = DataFunctionArgs & { request: Request; diff --git a/packages/hydrogen-remix/src/routing/proxy.ts b/packages/hydrogen-remix/src/routing/proxy.ts new file mode 100644 index 0000000000..9317452ce2 --- /dev/null +++ b/packages/hydrogen-remix/src/routing/proxy.ts @@ -0,0 +1,49 @@ +export async function proxyLiquidRoute( + request: Request, + storefrontDomain: string, + destinationPath: string, +): Promise { + const clientIP = request.headers.get('X-Shopify-Client-IP'); + const clientIPSig = request.headers.get('X-Shopify-Client-IP-Sig'); + + const headers = new Headers(); + const host = `${storefrontDomain}.myshopify.com`; + + const headersToFilterOut = ['connection']; + + for (const [key, value] of request.headers.entries()) { + if (!headersToFilterOut.includes(key)) { + headers.append( + key, + swapHostname(value, { + hostname: new URL(request.url).host, + newHostname: host, + }), + ); + } + } + + if (!clientIP || !clientIPSig) { + console.warn( + 'Proxying the online store is only available in Oxygen. This request is likely to be throttled.', + ); + } + + return fetch( + `https://${host}${ + destinationPath.startsWith('/') ? destinationPath : '/' + destinationPath + }`, + {headers}, + ).then((resp) => { + const headers = new Headers(resp.headers); + headers.delete('content-encoding'); + return new Response(resp.body, {headers}); + }); +} + +function swapHostname( + str: string, + {hostname, newHostname}: {hostname: string; newHostname: string}, +) { + return str.replaceAll(hostname, newHostname); +} diff --git a/templates/demo-store/app/entry.server.tsx b/templates/demo-store/app/entry.server.tsx index ad0babda01..7ca85a56b2 100644 --- a/templates/demo-store/app/entry.server.tsx +++ b/templates/demo-store/app/entry.server.tsx @@ -8,11 +8,6 @@ export default async function handleRequest( responseHeaders: Headers, remixContext: EntryContext, ) { - if (new URL(request.url).pathname === '/__health') { - // TODO: move this to @hydrogen/remix ? - return new Response(null, {status: 200}); - } - const body = await renderToReadableStream( , ); diff --git a/templates/demo-store/app/hooks/useDeferred.tsx b/templates/demo-store/app/hooks/useDeferred.tsx index 37f3e47ef9..06243d8bfe 100644 --- a/templates/demo-store/app/hooks/useDeferred.tsx +++ b/templates/demo-store/app/hooks/useDeferred.tsx @@ -24,5 +24,5 @@ export function useDeferred(resource: string, route: RouteMatch) { } // the [resource] was awaited in the loader return it - return route.data[resource]; + return route.data?.[resource]; } diff --git a/templates/demo-store/app/root.tsx b/templates/demo-store/app/root.tsx index 6243b579eb..b362edf531 100644 --- a/templates/demo-store/app/root.tsx +++ b/templates/demo-store/app/root.tsx @@ -32,9 +32,9 @@ import type {LayoutData} from '~/data'; export const handle = { // @todo - remove any and type the seo callback seo: (data: any) => ({ - title: data.layout.shop.name, + title: data?.layout?.shop?.name, bypassTitleTemplate: true, - titleTemplate: `%s | ${data.layout.shop.name}`, + titleTemplate: `%s | ${data?.layout?.shop?.name}`, }), }; @@ -103,7 +103,7 @@ export function CatchBoundary() { - + {isNotFound ? ( ) : ( @@ -129,7 +129,7 @@ export function ErrorBoundary({error}: {error: Error}) { - + diff --git a/templates/demo-store/oxygen.ts b/templates/demo-store/oxygen.ts index 87081ea968..50ddd3d5e9 100644 --- a/templates/demo-store/oxygen.ts +++ b/templates/demo-store/oxygen.ts @@ -1,4 +1,4 @@ -import {createRequestHandler} from '@shopify/hydrogen-remix'; +import {createRequestHandler, proxyLiquidRoute} from '@shopify/hydrogen-remix'; // The build remix app provided by remix build import * as remixBuild from 'remix-build'; import {HydrogenSession} from '~/lib/session.server'; @@ -11,6 +11,12 @@ const requestHandler = createRequestHandler({ shouldProxyAsset: () => false, }); +const storefrontConfig = { + publicStorefrontToken: '3b580e70970c4528da70c98e097c2fa0', + storeDomain: 'hydrogen-preview', + storefrontApiVersion: '2023-01', +}; + export default { async fetch( request: Request, @@ -25,6 +31,14 @@ export default { const session = await HydrogenSession.init(request, [env.SESSION_SECRET]); + if (new URL(request.url).pathname === '/proxy') { + return await proxyLiquidRoute( + request, + storefrontConfig.storeDomain, + '/pages/about', + ); + } + try { return await requestHandler( request,