Skip to content

Commit

Permalink
Merge pull request #15517 from Prince-Mendiratta/dynamic-api
Browse files Browse the repository at this point in the history
[Staging API] To Use Staging Server or not to use staging server
  • Loading branch information
mountiny authored Mar 6, 2023
2 parents 228a29b + 7323183 commit f95292a
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 43 deletions.
9 changes: 9 additions & 0 deletions config/proxyConfig.js
Original file line number Diff line number Diff line change
@@ -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-',
};
2 changes: 2 additions & 0 deletions config/webpack/webpack.dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
},
};
Expand Down
1 change: 1 addition & 0 deletions src/CONFIG.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,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,
};
15 changes: 9 additions & 6 deletions src/libs/HttpUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ import CONFIG from '../CONFIG';
import CONST from '../CONST';
import ONYXKEYS from '../ONYXKEYS';
import HttpsError from './Errors/HttpsError';
import shouldUseStagingServer from './shouldUseStagingServer';
import getPlatform from './getPlatform';
import proxyConfig from '../../config/proxyConfig';

// Desktop and web use staging config too so we we should default to staging API endpoint if on those platforms
const shouldDefaultToStaging = _.contains([CONST.PLATFORM.WEB, CONST.PLATFORM.DESKTOP], getPlatform());
let stagingServerToggleState = false;
let shouldUseStagingServer = false;
Onyx.connect({
key: ONYXKEYS.USER,
callback: val => stagingServerToggleState = lodashGet(val, 'shouldUseStagingServer', shouldDefaultToStaging),
callback: val => shouldUseStagingServer = lodashGet(val, 'shouldUseStagingServer', shouldDefaultToStaging),
});

let shouldFailAllRequests = false;
Expand Down Expand Up @@ -121,10 +121,13 @@ function xhr(command, data, type = CONST.NETWORK.METHOD.POST, shouldUseSecure =

let apiRoot = shouldUseSecure ? CONFIG.EXPENSIFY.SECURE_EXPENSIFY_URL : CONFIG.EXPENSIFY.URL_API_ROOT;

if (shouldUseStagingServer(stagingServerToggleState)) {
apiRoot = shouldUseSecure ? CONFIG.EXPENSIFY.STAGING_SECURE_EXPENSIFY_URL : CONFIG.EXPENSIFY.STAGING_EXPENSIFY_URL;
if (shouldUseStagingServer) {
if (CONFIG.IS_USING_WEB_PROXY) {
apiRoot = shouldUseSecure ? proxyConfig.STAGING_SECURE : proxyConfig.STAGING;
} else {
apiRoot = shouldUseSecure ? CONFIG.EXPENSIFY.STAGING_SECURE_EXPENSIFY_URL : CONFIG.EXPENSIFY.STAGING_EXPENSIFY_URL;
}
}

return processHTTPRequest(`${apiRoot}api?command=${command}`, type, formData, data.canCancel);
}

Expand Down
13 changes: 0 additions & 13 deletions src/libs/shouldUseStagingServer/index.js

This file was deleted.

13 changes: 0 additions & 13 deletions src/libs/shouldUseStagingServer/index.native.js

This file was deleted.

41 changes: 30 additions & 11 deletions web/proxy.js
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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,
Expand Down

0 comments on commit f95292a

Please sign in to comment.