humanmade / altis-local-server

Local Server module for Altis
https://www.altis-dxp.com/resources/docs/local-server/
16 stars 4 forks source link

Add an ngrok service for sharing the local environment #335

Open roborourke opened 3 years ago

roborourke commented 3 years ago

We have a working proof of concept courtesy of @kadamwhite so far:

Instructions:

server.js:

const express = require( 'express' );
const morgan = require( 'morgan' );
const proxy = require( 'http-proxy-middleware' );
const ngrok = require( 'ngrok' );

const createProxyMiddleware = proxy.createProxyMiddleware;
const responseInterceptor = proxy.responseInterceptor;

const PORT = 3000;
const HOST = 'localhost';
const TARGET_HOST = process.env.TARGET_HOST;

( async () => {
    const externalUrl = await ngrok.connect( PORT );

    const externalHost = externalUrl.replace( /https?:\/\//, '' );

    const app = express();

    app.use( morgan( 'dev' ) );

    // Proxy everything.
    app.use( '/', createProxyMiddleware( {
        target: TARGET_HOST,

        changeOrigin: true,

        // Defer res.end() to be handled by responseInterceptor.
        selfHandleResponse: true,

        /**
         * Intercept response and replace Snopes URL with ngrok URL.
         * Remove integrity hashes from markup so static assets load.
         **/
        onProxyRes: responseInterceptor( async ( responseBuffer ) => {
            return responseBuffer.toString( 'utf8' )
                // Point Tachyon URLs at a web-accessible bucket.
                .replace( /TARGET_HOST\/tachyon/ig, 'LIVE_HOST/tachyon' )
                // Everything else, rewrite so it will load that resource
                // over the ngrok connection.
                .replace( /TARGET_HOST/ig, externalHost )
                // Remove integrity hashes entirely :( or things won't work.
                .replace( /integrity=('[^']+'|"[^"]+")/ig, '' );
        } ),
    } ) );

    app.listen( PORT, HOST, () => {
        console.log( `Starting local Proxy at ${HOST}:${PORT}` );
        console.log( `Local environment is now available at ${ externalUrl }` );
    } );

} )();

package.json:

{
  "name": "local-server-proxy",
  "private": true,
  "version": "1.0.0",
  "description": "Relay web traffic from an external URL to Local Server",
  "main": "index.js",
  "scripts": {
    "proxy": "node server.js",
    "start": "node server.js"
  },
  "author": "Human Made",
  "license": "MIT",
  "dependencies": {
    "express": "^4.17.1",
    "http-proxy-middleware": "^2.0.1",
    "morgan": "^1.10.0",
    "ngrok": "^4.1.0"
  }
}

Acceptance criteria:

joehoyle commented 2 years ago

@rmccue mentioned https://github.com/beyondcode/expose which I think could make a quite interesting implementation.