From a26e93a3750d2f8968318f854be62098b3d145ab Mon Sep 17 00:00:00 2001 From: Prince Mendiratta Date: Thu, 23 Mar 2023 03:44:52 +0530 Subject: [PATCH 01/10] use staging api when toggle is on Signed-off-by: Prince Mendiratta --- config/proxyConfig.js | 9 ++++++++ config/webpack/webpack.dev.js | 2 ++ src/CONFIG.js | 1 + src/libs/ApiUtils.js | 6 +++++ web/proxy.js | 41 +++++++++++++++++++++++++---------- 5 files changed, 48 insertions(+), 11 deletions(-) create mode 100644 config/proxyConfig.js diff --git a/config/proxyConfig.js b/config/proxyConfig.js new file mode 100644 index 00000000000..0af64857d7b --- /dev/null +++ b/config/proxyConfig.js @@ -0,0 +1,9 @@ +/** + * These are the base API root used to send requests to the proxy. + * We only specify for staging URLs as API requests are sent to the production + * servers by default. + */ +module.exports = { + STAGING: '/staging-', + STAGING_SECURE: '/staging-secure-', +}; diff --git a/config/webpack/webpack.dev.js b/config/webpack/webpack.dev.js index 0b48c4e5f35..926dcd0bcc1 100644 --- a/config/webpack/webpack.dev.js +++ b/config/webpack/webpack.dev.js @@ -21,6 +21,8 @@ module.exports = (env = {}) => portfinder.getPortPromise({port: BASE_PORT}) : { proxy: { '/api': 'http://[::1]:9000', + '/staging-api': 'http://[::1]:9000', + '/staging-secure-api': 'http://[::1]:9000', '/chat-attachments': 'http://[::1]:9000', }, }; diff --git a/src/CONFIG.js b/src/CONFIG.js index 6b8d191b514..d430f9d9883 100644 --- a/src/CONFIG.js +++ b/src/CONFIG.js @@ -84,4 +84,5 @@ export default { DEV_PORT: process.env.PORT || 8080, E2E_TESTING: lodashGet(Config, 'E2E_TESTING', 'false') === 'true', SEND_CRASH_REPORTS: lodashGet(Config, 'SEND_CRASH_REPORTS', 'false') === 'true', + IS_USING_WEB_PROXY: getPlatform() === 'web' && useWebProxy, }; diff --git a/src/libs/ApiUtils.js b/src/libs/ApiUtils.js index 7d779248090..cdd271f88ad 100644 --- a/src/libs/ApiUtils.js +++ b/src/libs/ApiUtils.js @@ -4,6 +4,7 @@ import ONYXKEYS from '../ONYXKEYS'; import CONFIG from '../CONFIG'; import CONST from '../CONST'; import * as Environment from './Environment/Environment'; +import proxyConfig from '../../config/proxyConfig'; // To avoid rebuilding native apps, native apps use production config for both staging and prod // We use the async environment check because it works on all platforms @@ -41,6 +42,11 @@ function getApiRoot(request) { const shouldUseSecure = lodashGet(request, 'shouldUseSecure', false); if (shouldUseStagingServer) { + if (CONFIG.IS_USING_WEB_PROXY) { + return shouldUseSecure + ? proxyConfig.STAGING_SECURE + : proxyConfig.STAGING; + } return shouldUseSecure ? CONFIG.EXPENSIFY.STAGING_SECURE_API_ROOT : CONFIG.EXPENSIFY.STAGING_API_ROOT; diff --git a/web/proxy.js b/web/proxy.js index 768963d0810..4dc1a1018c1 100644 --- a/web/proxy.js +++ b/web/proxy.js @@ -1,21 +1,18 @@ const http = require('http'); const https = require('https'); +const proxyConfig = require('../config/proxyConfig'); require('dotenv').config(); if (process.env.USE_WEB_PROXY === 'false') { process.stdout.write('Skipping proxy as USE_WEB_PROXY was set to false.\n'); process.exit(); } - -let host = 'www.expensify.com'; - -// If we are testing against the staging API then we must use the correct host here or nothing with work. -if (/staging/.test(process.env.EXPENSIFY_URL)) { - host = 'staging.expensify.com'; -} +const host = new URL(process.env.EXPENSIFY_URL || 'https://www.expensify.com').hostname; +const stagingHost = new URL(process.env.STAGING_EXPENSIFY_URL || 'https://staging.expensify.com').hostname; +const stagingSecureHost = new URL(process.env.STAGING_SECURE_EXPENSIFY_URL || 'https://staging-secure.expensify.com').hostname; // eslint-disable-next-line no-console -console.log(`Creating proxy with host: ${host}`); +console.log(`Creating proxy with host: ${host} for production API and ${stagingHost} for staging API`); /** * Local proxy server that hits the production endpoint @@ -24,13 +21,35 @@ console.log(`Creating proxy with host: ${host}`); * environment that has no local API. */ const server = http.createServer((request, response) => { + let hostname = host; + let requestPath = request.url; + + /** + * When a request is matching a proxy config path we might direct it to a different host (e.g. staging) + * For requests matching proxy config patterns we replace the mapping url (prefix) with the actual path. + * This is done because the staging api root is only intended for the proxy, + * the actual server request must use the /api path. + * For example, + * /api?command=OpenReport => request sent to production server + * /staging-api?command=OpenReport => request sent to staging server + * /staging-secure-api?command=OpenReport => request sent to secure staging server + * /chat-attachments/46545... => request sent to production server + */ + if (request.url.startsWith(proxyConfig.STAGING_SECURE)) { + hostname = stagingSecureHost; + requestPath = request.url.replace(proxyConfig.STAGING_SECURE, '/'); + } else if (request.url.startsWith(proxyConfig.STAGING)) { + hostname = stagingHost; + requestPath = request.url.replace(proxyConfig.STAGING, '/'); + } + const proxyRequest = https.request({ - hostname: host, + hostname, method: 'POST', - path: request.url, + path: requestPath, headers: { ...request.headers, - host, + host: hostname, 'user-agent': request.headers['user-agent'].concat(' Development-NewDot/1.0'), }, port: 443, From 58b62758007c0c67653b1f150e6204f859310c90 Mon Sep 17 00:00:00 2001 From: Prince Mendiratta Date: Thu, 23 Mar 2023 03:51:03 +0530 Subject: [PATCH 02/10] update sample env to reflect changes Signed-off-by: Prince Mendiratta --- .env.example | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.env.example b/.env.example index cf13ef58301..232897143a1 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,8 @@ NEW_EXPENSIFY_URL=https://new.expensify.com/ SECURE_EXPENSIFY_URL=https://secure.expensify.com.dev/ EXPENSIFY_URL=https://www.expensify.com.dev/ +STAGING_EXPENSIFY_URL=https://staging.expensify.com.dev/ +STAGING_SECURE_EXPENSIFY_URL=https://staging-secure.expensify.com.dev/ EXPENSIFY_PARTNER_NAME=chat-expensify-com EXPENSIFY_PARTNER_PASSWORD=e21965746fd75f82bb66 PUSHER_APP_KEY=ac6d22b891daae55283a From e415cc2a64bd9dcdd31f638e99a6ff4c3ad53c08 Mon Sep 17 00:00:00 2001 From: Prince Mendiratta Date: Thu, 23 Mar 2023 04:55:32 +0530 Subject: [PATCH 03/10] redirect chat attachments as well Signed-off-by: Prince Mendiratta --- config/webpack/webpack.dev.js | 3 +-- web/proxy.js | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/webpack/webpack.dev.js b/config/webpack/webpack.dev.js index 926dcd0bcc1..2867d857ee0 100644 --- a/config/webpack/webpack.dev.js +++ b/config/webpack/webpack.dev.js @@ -21,8 +21,7 @@ module.exports = (env = {}) => portfinder.getPortPromise({port: BASE_PORT}) : { proxy: { '/api': 'http://[::1]:9000', - '/staging-api': 'http://[::1]:9000', - '/staging-secure-api': 'http://[::1]:9000', + '/staging': 'http://[::1]:9000', '/chat-attachments': 'http://[::1]:9000', }, }; diff --git a/web/proxy.js b/web/proxy.js index 4dc1a1018c1..9ff2d5c5029 100644 --- a/web/proxy.js +++ b/web/proxy.js @@ -34,6 +34,7 @@ const server = http.createServer((request, response) => { * /staging-api?command=OpenReport => request sent to staging server * /staging-secure-api?command=OpenReport => request sent to secure staging server * /chat-attachments/46545... => request sent to production server + * /staging-chat-attachments/46545... => request sent to staging server */ if (request.url.startsWith(proxyConfig.STAGING_SECURE)) { hostname = stagingSecureHost; From 85af20978554180b857fa61d80a298c6f9ff0273 Mon Sep 17 00:00:00 2001 From: Prince Mendiratta Date: Thu, 23 Mar 2023 23:39:56 +0530 Subject: [PATCH 04/10] update staging pattern Signed-off-by: Prince Mendiratta --- config/proxyConfig.js | 6 +++--- web/proxy.js | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/config/proxyConfig.js b/config/proxyConfig.js index 0af64857d7b..fa09c436461 100644 --- a/config/proxyConfig.js +++ b/config/proxyConfig.js @@ -1,9 +1,9 @@ /** - * These are the base API root used to send requests to the proxy. + * These are the base API roots used to send requests to the proxy. * We only specify for staging URLs as API requests are sent to the production * servers by default. */ module.exports = { - STAGING: '/staging-', - STAGING_SECURE: '/staging-secure-', + STAGING: '/staging/', + STAGING_SECURE: '/staging-secure/', }; diff --git a/web/proxy.js b/web/proxy.js index 9ff2d5c5029..2dfb76b7a08 100644 --- a/web/proxy.js +++ b/web/proxy.js @@ -31,10 +31,10 @@ const server = http.createServer((request, response) => { * the actual server request must use the /api path. * For example, * /api?command=OpenReport => request sent to production server - * /staging-api?command=OpenReport => request sent to staging server - * /staging-secure-api?command=OpenReport => request sent to secure staging server + * /staging/api?command=OpenReport => request sent to staging server + * /staging-secure/api?command=OpenReport => request sent to secure staging server * /chat-attachments/46545... => request sent to production server - * /staging-chat-attachments/46545... => request sent to staging server + * /staging/chat-attachments/46545... => request sent to staging server */ if (request.url.startsWith(proxyConfig.STAGING_SECURE)) { hostname = stagingSecureHost; From 2f6f575d6f2fa5005f649eb17b37ba38fe4d6597 Mon Sep 17 00:00:00 2001 From: Prince Mendiratta Date: Thu, 23 Mar 2023 23:57:34 +0530 Subject: [PATCH 05/10] remove .env.example updates Signed-off-by: Prince Mendiratta --- .env.example | 2 -- 1 file changed, 2 deletions(-) diff --git a/.env.example b/.env.example index 232897143a1..cf13ef58301 100644 --- a/.env.example +++ b/.env.example @@ -1,8 +1,6 @@ NEW_EXPENSIFY_URL=https://new.expensify.com/ SECURE_EXPENSIFY_URL=https://secure.expensify.com.dev/ EXPENSIFY_URL=https://www.expensify.com.dev/ -STAGING_EXPENSIFY_URL=https://staging.expensify.com.dev/ -STAGING_SECURE_EXPENSIFY_URL=https://staging-secure.expensify.com.dev/ EXPENSIFY_PARTNER_NAME=chat-expensify-com EXPENSIFY_PARTNER_PASSWORD=e21965746fd75f82bb66 PUSHER_APP_KEY=ac6d22b891daae55283a From 4c352b875e3442ce88b4c53b67eb0100c98330d2 Mon Sep 17 00:00:00 2001 From: Prince Mendiratta Date: Fri, 24 Mar 2023 01:04:27 +0530 Subject: [PATCH 06/10] hide the staging server toggle for internal dev Signed-off-by: Prince Mendiratta --- src/components/TestToolMenu.js | 3 ++- src/components/TestToolRow.js | 10 +++++++++- src/libs/ApiUtils.js | 4 ++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/components/TestToolMenu.js b/src/components/TestToolMenu.js index c1512a805bf..687f7be4fd3 100644 --- a/src/components/TestToolMenu.js +++ b/src/components/TestToolMenu.js @@ -15,6 +15,7 @@ import networkPropTypes from './networkPropTypes'; import compose from '../libs/compose'; import {withNetwork} from './OnyxProvider'; import * as ApiUtils from '../libs/ApiUtils'; +import CONFIG from '../CONFIG'; const propTypes = { /** User object in Onyx */ @@ -43,7 +44,7 @@ const TestToolMenu = props => ( {/* Option to switch between staging and default api endpoints. This enables QA and internal testers to take advantage of sandbox environments for 3rd party services like Plaid and Onfido. */} - + User.setShouldUseStagingServer( diff --git a/src/components/TestToolRow.js b/src/components/TestToolRow.js index 5364f44537b..250708639a3 100644 --- a/src/components/TestToolRow.js +++ b/src/components/TestToolRow.js @@ -10,9 +10,16 @@ const propTypes = { /** Control component jsx */ children: PropTypes.node.isRequired, + + /** Conditionally hide the row */ + isHidden: PropTypes.bool, +}; + +const defaultProps = { + isHidden: false, }; -const TestToolRow = props => ( +const TestToolRow = props => !props.isHidden && ( @@ -26,6 +33,7 @@ const TestToolRow = props => ( ); TestToolRow.propTypes = propTypes; +TestToolRow.defaultProps = defaultProps; TestToolRow.displayName = 'TestToolRow'; export default TestToolRow; diff --git a/src/libs/ApiUtils.js b/src/libs/ApiUtils.js index cdd271f88ad..08533c83b07 100644 --- a/src/libs/ApiUtils.js +++ b/src/libs/ApiUtils.js @@ -18,8 +18,8 @@ Environment.getEnvironment() Onyx.connect({ key: ONYXKEYS.USER, callback: (val) => { - // Toggling between APIs is not allowed on production - if (ENV_NAME === CONST.ENVIRONMENT.PRODUCTION) { + // Toggling between APIs is not allowed on production and internal dev environment + if (ENV_NAME === CONST.ENVIRONMENT.PRODUCTION || CONFIG.IS_USING_LOCAL_WEB) { shouldUseStagingServer = false; return; } From 2349ebf7f948b1d199f5b5b5d4a976cec2a2cfe7 Mon Sep 17 00:00:00 2001 From: Prince Mendiratta Date: Fri, 24 Mar 2023 15:08:46 +0530 Subject: [PATCH 07/10] inline ternary for staging toggle Signed-off-by: Prince Mendiratta --- src/components/TestToolMenu.js | 21 ++++++++++++--------- src/components/TestToolRow.js | 10 +--------- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/src/components/TestToolMenu.js b/src/components/TestToolMenu.js index 687f7be4fd3..5c473de7fd4 100644 --- a/src/components/TestToolMenu.js +++ b/src/components/TestToolMenu.js @@ -43,15 +43,18 @@ const TestToolMenu = props => ( {/* Option to switch between staging and default api endpoints. - This enables QA and internal testers to take advantage of sandbox environments for 3rd party services like Plaid and Onfido. */} - - User.setShouldUseStagingServer( - !lodashGet(props, 'user.shouldUseStagingServer', ApiUtils.isUsingStagingApi()), - )} - /> - + This enables QA, internal testers and external devs to take advantage of sandbox environments for 3rd party services like Plaid and Onfido. + This toggle is rendered conditionally to not display this option for internal employees as they make environment changes directly to the .env file. */} + {CONFIG.IS_USING_LOCAL_WEB && ( + + User.setShouldUseStagingServer( + !lodashGet(props, 'user.shouldUseStagingServer', ApiUtils.isUsingStagingApi()), + )} + /> + + )} {/* When toggled the app will be forced offline. */} diff --git a/src/components/TestToolRow.js b/src/components/TestToolRow.js index 250708639a3..5364f44537b 100644 --- a/src/components/TestToolRow.js +++ b/src/components/TestToolRow.js @@ -10,16 +10,9 @@ const propTypes = { /** Control component jsx */ children: PropTypes.node.isRequired, - - /** Conditionally hide the row */ - isHidden: PropTypes.bool, -}; - -const defaultProps = { - isHidden: false, }; -const TestToolRow = props => !props.isHidden && ( +const TestToolRow = props => ( @@ -33,7 +26,6 @@ const TestToolRow = props => !props.isHidden && ( ); TestToolRow.propTypes = propTypes; -TestToolRow.defaultProps = defaultProps; TestToolRow.displayName = 'TestToolRow'; export default TestToolRow; From 45fc2b7cbe2afd3187a326d3c20a169ce3e1c9a4 Mon Sep 17 00:00:00 2001 From: Prince Mendiratta Date: Fri, 24 Mar 2023 15:17:47 +0530 Subject: [PATCH 08/10] update comment Signed-off-by: Prince Mendiratta --- src/components/TestToolMenu.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/TestToolMenu.js b/src/components/TestToolMenu.js index 5c473de7fd4..1a53dd61435 100644 --- a/src/components/TestToolMenu.js +++ b/src/components/TestToolMenu.js @@ -44,7 +44,7 @@ const TestToolMenu = props => ( {/* Option to switch between staging and default api endpoints. This enables QA, internal testers and external devs to take advantage of sandbox environments for 3rd party services like Plaid and Onfido. - This toggle is rendered conditionally to not display this option for internal employees as they make environment changes directly to the .env file. */} + This toggle is not rendered for internal devs as they make environment changes directly to the .env file. */} {CONFIG.IS_USING_LOCAL_WEB && ( Date: Fri, 24 Mar 2023 18:43:54 +0530 Subject: [PATCH 09/10] correct condition Signed-off-by: Prince Mendiratta --- src/components/TestToolMenu.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/TestToolMenu.js b/src/components/TestToolMenu.js index 1a53dd61435..eaae9aec984 100644 --- a/src/components/TestToolMenu.js +++ b/src/components/TestToolMenu.js @@ -45,7 +45,7 @@ const TestToolMenu = props => ( {/* Option to switch between staging and default api endpoints. This enables QA, internal testers and external devs to take advantage of sandbox environments for 3rd party services like Plaid and Onfido. This toggle is not rendered for internal devs as they make environment changes directly to the .env file. */} - {CONFIG.IS_USING_LOCAL_WEB && ( + {!CONFIG.IS_USING_LOCAL_WEB && ( Date: Sat, 25 Mar 2023 00:18:51 +0530 Subject: [PATCH 10/10] remove use of env vars in proxy Signed-off-by: Prince Mendiratta --- web/proxy.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/proxy.js b/web/proxy.js index 2dfb76b7a08..3bce0851460 100644 --- a/web/proxy.js +++ b/web/proxy.js @@ -7,9 +7,9 @@ if (process.env.USE_WEB_PROXY === 'false') { process.stdout.write('Skipping proxy as USE_WEB_PROXY was set to false.\n'); process.exit(); } -const host = new URL(process.env.EXPENSIFY_URL || 'https://www.expensify.com').hostname; -const stagingHost = new URL(process.env.STAGING_EXPENSIFY_URL || 'https://staging.expensify.com').hostname; -const stagingSecureHost = new URL(process.env.STAGING_SECURE_EXPENSIFY_URL || 'https://staging-secure.expensify.com').hostname; +const host = 'www.expensify.com'; +const stagingHost = 'staging.expensify.com'; +const stagingSecureHost = 'staging-secure.expensify.com'; // eslint-disable-next-line no-console console.log(`Creating proxy with host: ${host} for production API and ${stagingHost} for staging API`);