Proxy With Cloudflare Workers
For production use, we dont recommend calling Elasticsearch directly from the browser. Thankfully, Searchkit provides a way to proxy the search request through to a node API. This is really easy to setup.
Below this creates an API which transforms the instantsearch requests sent from the browser into Elasticsearch queries and transforms the responses into instantsearch results.
Get Started with Cloudflare Workers
Follow the guide here (opens in a new tab) to get started with Cloudflare Workers.
Checkout example project
You
curl https://codeload.github.com/searchkit/searchkit/tar.gz/main | \
tar -xz --strip=2 searchkit-main/examples/with-cloudflare-workers
or view the example codebase on github here (opens in a new tab)
Create a new project
npx wrangler init my-searchkit-proxy-api
cd my-searchkit-proxy-api
Install @searchkit/api and searchkit
yarn add @searchkit/api searchkit
Update the Cloudflare worker
Edit the src/index.js
file to look like this, replacing the connection
and search_settings
with your own.
import Client from "@searchkit/api";
const client = Client({
connection: {
host: "<ELASTICSEARCH_URL>",
// if you are authenticating with api key
// https://www.searchkit.co/docs/guides/setup-elasticsearch#connecting-with-api-key
// apiKey: '###'
// if you are authenticating with username/password
// https://www.searchkit.co/docs/guides/setup-elasticsearch#connecting-with-usernamepassword
// auth: {
// username: "elastic",
// password: "changeme"
// },
},
search_settings: {
highlight_attributes: ["highlightField1", "highlightField2"],
search_attributes: ["title", "description"],
result_attributes: ["title", "description"],
facet_attributes: [
"type",
{ attribute: "actors", field: "actors.keyword" },
],
},
});
// Handle CORS preflight requests
async function handleOptions(request: Request) {
return new Response(null, {
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type",
},
});
}
async function handleRequest(event: FetchEvent) {
if (event.request.method === "OPTIONS") {
// Handle CORS preflight requests
return handleOptions(event.request);
}
const body = await event.request.json();
const results = await client.handleRequest(body);
return new Response(JSON.stringify(results), {
headers: {
"content-type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, HEAD, POST, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type",
},
});
}
addEventListener("fetch", (event) => {
return event.respondWith(handleRequest(event));
});
then run your worker locally
npx wrangler dev
Update the Searchkit client on frontend
and then we update the instantsearch client to use the API.
The searchkit configuration and import are no longer needed. Rather than the elasticsearch requests being generated and performed on the browser, the search state is instead sent to the API, which then generates and performs requests to Elasticsearch on the server.
const searchClient = instantsearch({
indexName: "imdb_movies",
searchClient: SearchkitInstantsearchClient({
url: "http://localhost:8787/",
}),
});
Production
When you are ready to deploy to production, run
npx wrangler publish
and then update the url in the frontend to point to the new url.
And that's it! You dont need to worry about the security of your Elasticsearch cluster, and you can scale your API independently of your search cluster.