mrmd-server 0.1.8 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mrmd-server",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "HTTP server for mrmd - run mrmd in any browser, access from anywhere",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/server.js CHANGED
@@ -188,6 +188,40 @@ export async function createServer(config) {
188
188
  app.use('/api/settings', createSettingsRoutes(context));
189
189
  app.use('/api/r', createRRoutes(context));
190
190
 
191
+ // Proxy for localhost services (bash, pty, etc.)
192
+ // Routes /proxy/:port/* to http://127.0.0.1:port/*
193
+ app.use('/proxy/:port', async (req, res) => {
194
+ const { port } = req.params;
195
+ const targetPath = req.url; // Includes query string
196
+ const targetUrl = `http://127.0.0.1:${port}${targetPath}`;
197
+
198
+ try {
199
+ const response = await fetch(targetUrl, {
200
+ method: req.method,
201
+ headers: {
202
+ 'Content-Type': req.headers['content-type'] || 'application/json',
203
+ 'Accept': req.headers['accept'] || '*/*',
204
+ },
205
+ body: ['GET', 'HEAD'].includes(req.method) ? undefined : JSON.stringify(req.body),
206
+ });
207
+
208
+ // Forward response headers
209
+ res.status(response.status);
210
+ response.headers.forEach((value, key) => {
211
+ if (!['content-encoding', 'transfer-encoding', 'content-length'].includes(key.toLowerCase())) {
212
+ res.setHeader(key, value);
213
+ }
214
+ });
215
+
216
+ // Forward response body
217
+ const data = await response.text();
218
+ res.send(data);
219
+ } catch (err) {
220
+ console.error(`[proxy] Failed to proxy to ${targetUrl}:`, err.message);
221
+ res.status(502).json({ error: `Proxy error: ${err.message}` });
222
+ }
223
+ });
224
+
191
225
  // Serve http-shim.js
192
226
  app.get('/http-shim.js', (req, res) => {
193
227
  res.sendFile(path.join(__dirname, '../static/http-shim.js'));
@@ -44,6 +44,32 @@
44
44
  window.WebSocket.CLOSING = OriginalWebSocket.CLOSING;
45
45
  window.WebSocket.CLOSED = OriginalWebSocket.CLOSED;
46
46
 
47
+ // ==========================================================================
48
+ // Fetch Proxy Interceptor
49
+ // ==========================================================================
50
+ // Intercept fetch requests to localhost services (bash, pty) and route through proxy
51
+ const OriginalFetch = window.fetch;
52
+ window.fetch = function(input, init) {
53
+ let url = typeof input === 'string' ? input : input.url;
54
+
55
+ // Check if this is a request to localhost service
56
+ const match = url.match(/^https?:\/\/(?:127\.0\.0\.1|localhost):(\d+)\/(.*)$/);
57
+ if (match) {
58
+ const [, port, path] = match;
59
+ // Route through server proxy
60
+ const proxyUrl = new URL(`/proxy/${port}/${path}`, BASE_URL);
61
+ console.log(`[http-shim] Proxying fetch: ${url} -> ${proxyUrl.toString()}`);
62
+
63
+ if (typeof input === 'string') {
64
+ input = proxyUrl.toString();
65
+ } else {
66
+ input = new Request(proxyUrl.toString(), input);
67
+ }
68
+ }
69
+
70
+ return OriginalFetch.call(window, input, init);
71
+ };
72
+
47
73
  // ==========================================================================
48
74
  // HTTP Client
49
75
  // ==========================================================================