Google Cloud Load balancer supports url rewrite only as a prefix to the url, so you can transform a request to host/url
to host/prefix/url
.
For my usecase I’m using a storage bucket as a backend, but if a request comes in to host/url
I would need it to proxy it to host/host/url
so that it adds the host as a dynamic prefix to the url.
This is not supported out of the box so as fix I’ve changed the backend to a cloud function which proxies the request to the target bucket.
Embedded from https://gist.github.com/ecyshor/0138ea1f8b0b16b1b7357a936d060b66#proxy.ts
import * as functions from 'firebase-functions';
import * as http from 'http';
const BUCKET_NAME = "target-bucket"
exports.rewriteGCSRequest = functions.https.onRequest((oreq: any, ores: any) => {
const redirectPath = oreq.originalUrl === '/' ? '/index.html' : oreq.originalUrl
const options = {
// host to forward to
host: 'storage.googleapis.com',
// port to forward to
port: 80,
// path to forward to
path: `${BUCKET_NAME}/${oreq.hostname}${redirectPath}`,
// request method
method: 'GET',
// headers to send
headers: oreq.headers,
agent: httpAgent
};
const creq = http
.request(options, pres => {
// set http status code based on proxied response
ores.writeHead(pres.statusCode, pres.headers);
// wait for data
pres.on('data', chunk => {
ores.write(chunk);
});
pres.on('close', () => {
// closed, let's end client request as well
ores.end();
});
pres.on('end', () => {
// finished, let's finish client request as well
ores.end();
});
})
.on('error', e => {
// we got an error
console.error(e);
try {
// attempt to set error message and http status
ores.writeHead(500);
ores.write(e.message);
} catch (error) {
// ignore
}
ores.end();
});
creq.end();
})
Check the original code here
The function also proxies all the requests to the root /
to index.html
, that is optional and can actually be configured directly in the load balancer.