-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(headless SSR): support navigator context in both Engine and fetc…
…h/hydrate functions (#4231) Introducing a method for configuring the navigator context provider. Users are alerted with a warning if the navigator context is not established on both the client and server sides. I also updated the samples to demonstrate the navigator's application within a Next.js framework, though the approach is not exclusive to this framework. There are two methods for setting the navigator context: 1. During engine configuration. 2. While initializing the app's static state and hydrating the app state, if the first method is impractical. The example in the SSR samples highlights a scenario where, due to the framework's limitations, setting the navigator context directly within the engine configuration is not feasible because headers are not yet available. In such cases, the second method is recommended. However, this approach necessitates invoking `setNavigatorContextProvider` on both the server and client sides, increasing the potential for user errors. To address this, a warning is issued if the setup is not correctly implemented.
- Loading branch information
Showing
7 changed files
with
141 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
63 changes: 63 additions & 0 deletions
63
packages/samples/headless-ssr-commerce/app/_lib/navigatorContextProvider.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import {NavigatorContext} from '@coveo/headless/ssr-commerce'; | ||
import type {ReadonlyHeaders} from 'next/dist/server/web/spec-extension/adapters/headers'; | ||
|
||
/** | ||
* This class implements the NavigatorContext interface from Coveo's SSR commerce sub-package. | ||
* It is designed to work within a Next.js environment, providing a way to extract | ||
* navigation-related context from Next.js request headers. This context will then be | ||
* pass to subsequent search requests. | ||
*/ | ||
export class NextJsNavigatorContext implements NavigatorContext { | ||
/** | ||
* Initializes a new instance of the NextJsNavigatorContext class. | ||
* @param headers The readonly headers from a Next.js request, providing access to request-specific data. | ||
*/ | ||
constructor(private headers: ReadonlyHeaders) {} | ||
|
||
/** | ||
* Retrieves the referrer URL from the request headers. | ||
* Some browsers use 'referer' while others may use 'referrer'. | ||
* @returns The referrer URL if available, otherwise undefined. | ||
*/ | ||
get referrer() { | ||
return this.headers.get('referer') || this.headers.get('referrer'); | ||
} | ||
|
||
/** | ||
* Retrieves the user agent string from the request headers. | ||
* @returns The user agent string if available, otherwise undefined. | ||
*/ | ||
get userAgent() { | ||
return this.headers.get('user-agent'); | ||
} | ||
|
||
/** | ||
* Placeholder for the location property. Needs to be implemented based on the application's requirements. | ||
* @returns Currently returns a 'TODO:' string. | ||
*/ | ||
get location() { | ||
return 'TODO:'; | ||
} | ||
|
||
/** | ||
* Fetches the unique client ID that was generated earlier by the middleware. | ||
* @returns The client ID. | ||
*/ | ||
get clientId() { | ||
const clientId = this.headers.get('x-coveo-client-id'); | ||
return clientId!; | ||
} | ||
|
||
/** | ||
* Marshals the navigation context into a format that can be used by Coveo's headless library. | ||
* @returns An object containing clientId, location, referrer, and userAgent properties. | ||
*/ | ||
get marshal(): NavigatorContext { | ||
return { | ||
clientId: this.clientId, | ||
location: this.location, | ||
referrer: this.referrer, | ||
userAgent: this.userAgent, | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import {NextRequest, NextResponse} from 'next/server'; | ||
|
||
export default function middleware(request: NextRequest) { | ||
const response = NextResponse.next(); | ||
const requestHeaders = new Headers(request.headers); | ||
const uuid = crypto.randomUUID(); | ||
requestHeaders.set('x-coveo-client-id', uuid); | ||
response.headers.set('x-coveo-client-id', uuid); | ||
return response; | ||
} |