-
Notifications
You must be signed in to change notification settings - Fork 990
/
Copy pathcloudRunProxy.ts
77 lines (67 loc) · 2.64 KB
/
cloudRunProxy.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import { RequestHandler } from "express";
import { Client } from "../apiv2";
import { cloudRunApiOrigin } from "../api";
import { errorRequestHandler, proxyRequestHandler } from "./proxy";
import { FirebaseError } from "../error";
import { logger } from "../logger";
import { needProjectId } from "../projectUtils";
export interface CloudRunProxyOptions {
project?: string;
}
export interface CloudRunProxyRewrite {
run: {
serviceId: string;
region?: string;
};
}
const cloudRunCache: { [s: string]: string } = {};
const apiClient = new Client({ urlPrefix: cloudRunApiOrigin(), apiVersion: "v1" });
async function getCloudRunUrl(rewrite: CloudRunProxyRewrite, projectId: string): Promise<string> {
const alreadyFetched = cloudRunCache[`${rewrite.run.region}/${rewrite.run.serviceId}`];
if (alreadyFetched) {
return Promise.resolve(alreadyFetched);
}
const path = `/projects/${projectId}/locations/${rewrite.run.region || "us-central1"}/services/${
rewrite.run.serviceId
}`;
try {
logger.info(`[hosting] Looking up Cloud Run service "${path}" for its URL`);
const res = await apiClient.get<{ status?: { url?: string } }>(path);
const url = res.body.status?.url;
if (!url) {
throw new FirebaseError("Cloud Run URL doesn't exist in response.");
}
cloudRunCache[`${rewrite.run.region}/${rewrite.run.serviceId}`] = url;
return url;
} catch (err: any) {
throw new FirebaseError(`Error looking up URL for Cloud Run service: ${err}`, {
original: err,
});
}
}
/**
* Returns a function which, given a CloudRunProxyRewrite, returns a Promise
* that resolves with a middleware-like function that proxies the request to
* the live Cloud Run service running within the given project.
*/
export default function (
options: CloudRunProxyOptions,
): (r: CloudRunProxyRewrite) => Promise<RequestHandler> {
return async (rewrite: CloudRunProxyRewrite) => {
if (!rewrite.run) {
// SuperStatic wouldn't send it here, but we should check
return errorRequestHandler('Cloud Run rewrites must have a valid "run" field.');
}
if (!rewrite.run.serviceId) {
return errorRequestHandler("Cloud Run rewrites must supply a service ID.");
}
if (!rewrite.run.region) {
rewrite.run.region = "us-central1"; // Default region
}
logger.info(`[hosting] Cloud Run rewrite ${JSON.stringify(rewrite)} triggered`);
const textIdentifier = `Cloud Run service "${rewrite.run.serviceId}" for region "${rewrite.run.region}"`;
return getCloudRunUrl(rewrite, needProjectId(options))
.then((url) => proxyRequestHandler(url, textIdentifier))
.catch(errorRequestHandler);
};
}