Skip to content

Commit

Permalink
Start using Node Proxy Server for the backend.
Browse files Browse the repository at this point in the history
* Working locally.

* Remove reliance on secrets on client.

* Ask for latest in Breadboard.

* Update package-lock.json.

* Introduce more events to Runner.

* Update to the latest Breadboard.

* Update deps.
  • Loading branch information
dglazkov authored May 16, 2024
1 parent adb9843 commit f6259d9
Show file tree
Hide file tree
Showing 12 changed files with 6,333 additions and 4,296 deletions.
6,238 changes: 3,458 additions & 2,780 deletions package-lock.json

Large diffs are not rendered by default.

103 changes: 103 additions & 0 deletions seeds/team-experiments/api/proxy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/**
* @license
* Copyright 2024 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

import {
AnyProxyRequestMessage,
HTTPServerTransport,
ProxyServer,
ProxyServerConfig,
ServerResponse,
hasOrigin,
} from "@google-labs/breadboard/remote";
import type { VercelRequest, VercelResponse } from "@vercel/node";

import Core from "@google-labs/core-kit";
import { asRuntimeKit } from "@google-labs/breadboard";
import { IncomingMessage } from "http";

const config: ProxyServerConfig = {
kits: [asRuntimeKit(Core)],
proxy: [
"fetch",
{
node: "secrets",
tunnel: {
GEMINI_KEY: {
to: "fetch",
when: {
url: hasOrigin("https://generativelanguage.googleapis.com"),
},
},
SCRAPING_BEE_KEY: {
to: "fetch",
when: {
url: hasOrigin("https://app.scrapingbee.com/"),
},
},
},
},
],
};

class ResponseAdapter implements ServerResponse {
#response: VercelResponse;

constructor(response: VercelResponse) {
this.#response = response;
}

header(field: string, value: string): unknown {
this.#response.setHeader(field, value);
return this;
}

write(chunk: unknown): boolean {
return this.#response.write(chunk);
}

end(): unknown {
this.#response.end();
return this;
}
}

const extractRequestBody = async (request: IncomingMessage) => {
return new Promise<AnyProxyRequestMessage>((resolve, reject) => {
let body = "";
request.on("data", (chunk) => {
body += chunk.toString();
});
request.on("end", () => {
resolve(JSON.parse(body) as AnyProxyRequestMessage);
});
request.on("error", reject);
});
};

export default async function handler(
request: VercelRequest,
response: VercelResponse
) {
if (request.method === "GET") {
response.setHeader("Content-Type", "text/html");
response.write("<H1>USE POST</H1>");
response.end();
return;
}
const body = await extractRequestBody(request);
const server = new ProxyServer(
new HTTPServerTransport({ body }, new ResponseAdapter(response))
);
try {
await server.serve(config);
} catch (e) {
response.statusCode = 500;
response.setHeader("Content-Type", "text/html");
response.write(`<H1>Server Error: ${(e as Error).message}</H1>`);
response.end();
}
return;
}
23 changes: 10 additions & 13 deletions seeds/team-experiments/api/secrets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,18 @@
* SPDX-License-Identifier: Apache-2.0
*/

export const edge = true;
export const headers = {
"Content-Type": "application/json",
};
export const streaming = true;

import { config } from "dotenv";

export default async function handler() {
const { parsed, error } = config();
export function GET() {
const model = process.env.model;
let result;
if (error) {
if (!model) {
result = JSON.stringify({ error: "Could not retrieve secrets" });
} else {
result = JSON.stringify({ parsed });
result = JSON.stringify({ parsed: { model } });
}
return new Response(result, { status: 200 });
return new Response(result, {
status: 200,
headers: {
"Content-Type": "application/json",
},
});
}
Loading

0 comments on commit f6259d9

Please sign in to comment.