Puuh. That was a good days work, but I came up with a solution:
I wrote a small proxy server script, located in scripts/webAppDevProxy/index.js
:
import http from "http";
import { devProxyHost, devProxyPort } from "./constants.js";
http
.createServer((req, res) => {
// Get target URL from request URL "path"
const targetUrl = req.url.replace(/^\//, "");
console.log(`incoming request ➜ URL: ${targetUrl} | Method: ${req.method}`);
// Setting headers
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader(
"Access-Control-Allow-Headers",
"Content-Type, Authorization"
);
// Handle preflight requests:
if (req.method === "OPTIONS") {
res.writeHead(200);
res.end();
return;
}
// Parse request body:
req.body = "";
req.on("data", (chunk) => {
req.body += chunk;
});
// Forward the request
req.on("end", async () => {
try {
// Fetch target URL with data from proxy request
const response = await fetch(targetUrl, {
method: req.method,
headers: {
"Content-Type":
req.headers.get("content-type") || "application/json",
},
body: req.body,
});
// Get content type of response
const resContentType =
response.headers.get("content-type") || "application/json";
// Set content type hedaer of response
res.setHeader("Content-Type", resContentType);
console.log(`Resolving request ➜ Status: ${response.status}`);
// Resolve request to proxy with data from forwarded request:
res.writeHead(response.status);
res.end(JSON.stringify(await response.json()));
} catch (error) {
console.log(`Resolving request ➜ Status: 500`);
// Set content type hedaer of response
res.setHeader("Content-Type", "application/json");
// Resolve rewuest to proxy server with error
res.writeHead(500);
res.end(
JSON.stringify({
error: {
code: 500,
message: "500: Internal Server Error",
},
})
);
}
});
})
.listen(devProxyPort, devProxyHost, () => {
console.log(
`Web App Dev Proxy listening at http://${devProxyHost}:${devProxyPort}`
);
})
.on("error", (err) => {
console.log(`Error while setting up server: ${err.message}`);
});
This basically takes any request, to the proxy server, forwards it to the target URL and forwards the response back to the app. (As a good proxy does.
)
The proxy is started, using a simple npm run
command in package.json
:
{
scripts: {
"startDevProxy": "node scripts/webAppDevProxy"
}
}
Within the app, i defined a constant, that i can use to discern wether the app is currently running locally as a web app or not:
import { Capacitor } from "@capacitor/core";
const ENV = import.meta.env;
const isLocalWebApp = !Capacitor.isNativePlatform() && ENV.MODE === "development";
Now, whenever I’m doing a tech request in the app, I can adjust my URLs accordingly:
// @ts-ignore
import { devProxyUrl } from "../../scripts/webAppDevProxy/constants.js";
const urlToFetch =
(isLocalWebApp ? `${devProxyUrl}/` : "") + "https://api.example.com";
const response = fetch(urlToFetch, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: {
data: "Body data",
},
});
The “real” code is a bit more complex and structured into multiple files. Mostly, because I do a real preflight check for allowed origins and my logs are a lot more verbose. I can piece together a small GitHub repo with a brief explanation on how to use the proxy if anyone is interested.
Thanks for your help guys, cheers! 