3

I have a spring-boot application which implements Kerberos single-sign-on and exposes both REST and STOMP websockets over HTTPS/WSS. I need to set this up with a proxy for local development.

I've attempted to add both the following to package.json

"proxy": {
  "/ws": {
    "target": "wss://my.host.name.com:8080",
    "ws": true,
    "ssl": true
  },
  "/api": {
    "target": "https://my.host.name.com:8080",
    "ssl": true
  }
}

&

"proxy": "https://my.host.name.com:8080"

And then change my client code:

===================================================================
--- app/src/api/index.ts    (revision 6fcacd98ec61cda85d7dfa7fe5d5f5c12aafbe8a)
+++ app/src/api/index.ts    (date 1540455521933)
@@ -5,7 +5,7 @@
 import Statistics from '../types/Statistics';

 export function submitPricerList(list: ReadonlyArray<PricerCoreInputs | null>): Promise<string> {
-    return fetch('https://my.host.name.com:8080/api/pricer-list', {
+    return fetch('/api/pricer-list', {
         body: JSON.stringify(list),
         credentials: 'include',
         headers: {
@@ -28,7 +28,7 @@
 }

 export function initialSnapshot(): Promise<SnapshotWithChartableCurves | null> {
-    return fetch('https://my.host.name.com:8080/api/initial-snapshot', {
+    return fetch('/api/initial-snapshot', {
         credentials: 'include',
         headers: {
             'Accept': 'application/json'

===================================================================
--- app/src/containers/App.tsx  (revision 6fcacd98ec61cda85d7dfa7fe5d5f5c12aafbe8a)
+++ app/src/containers/App.tsx  (date 1540455521900)
@@ -74,7 +74,7 @@
         super(props);

         const stompClient = new StompJs.Client({
-            brokerURL: `wss://my.host.name.com:8080/ws/gs-guide-websocket`,
+            brokerURL: `wss://${window.location.host}/ws/gs-guide-websocket`,
             debug: (str) => {
                 this.logger.log({level: 'debug', message: str});
             },

With the simple proxy config HTTPS proxying works and WSS does not but with the detailed proxy config neither work.

How can I configure the proxy settings so both HTTPS and WSS are routed correctly during development?

Jon Freedman
  • 9,469
  • 4
  • 39
  • 58

1 Answers1

0

We ended up solving this problem using a setupProxy.js script which makes use of http-proxy-middleware.

We then picked some environment variables to control the behavior e.g. REACT_APP_HOST_NAME and REACT_APP_FORCE_PROXY_PROTOCOL with the resultant code a bit like this:

const proxy = require('http-proxy-middleware');

module.exports = function(app) {
    const developmentHostName = process.env.REACT_APP_HOST_NAME;
    if (process.env.NODE_ENV === 'development' &&  developmentHostName) {
        const protocol = process.env.REACT_APP_FORCE_PROXY_PROTOCOL || 'https';
        const hostName = `${developmentHostName.trim()}.my.domain.com:8080`;
        app.use(
            proxy('/api', {
                target: `${protocol}://${hostName}`,
                secure: false,
                onProxyRes(proxyRes) {
                    // protocolRewrite option is currently only applicable to 301/302/307/308 response codes
                    const locationHeader = proxyRes.headers['location'];
                    if (locationHeader !== undefined) {
                        const protocolEnd = locationHeader.indexOf('://');
                        const locationProtocol = locationHeader.substring(0, protocolEnd);
                        if (locationProtocol !== 'http') {
                            proxyRes.headers['location'] = 'http' + locationHeader.substring(protocolEnd);
                        }
                    }
                }
            })
        );
    }
};

And our application contains something a bit like this

const hostname = window.location.hostname;
const developmentHostName = process.env.REACT_APP_HOST_NAME || hostname;
const hostAndPort = hostname === 'localhost' ? `${developmentHostName.trim()}.my.domain.com:8080` : `${hostname}:${window.location.port}`;
const protocol = process.env.REACT_APP_FORCE_PROXY_PROTOCOL || window.location.protocol;
const wsProtocol = protocol.length > 4 && protocol.substring(0, 5) === 'https' ? 'wss:' : 'ws:';

This means our websocket connections are not proxied, but they do at least work

Jon Freedman
  • 9,469
  • 4
  • 39
  • 58