Proxy requests to the backend via the frontend.

master
Pacman Ghost 4 years ago
parent cbb5039321
commit a518ba7f5d
  1. 3
      asl_articles/globvars.py
  2. 2
      web/Dockerfile
  3. 1
      web/docker/env
  4. 22
      web/docker/nginx-default.conf
  5. 68
      web/package-lock.json
  6. 1
      web/package.json
  7. 10
      web/src/App.js
  8. 11
      web/src/setupProxy.js

@ -11,6 +11,9 @@ from asl_articles.config.constants import APP_NAME, APP_VERSION
# ---------------------------------------------------------------------
# NOTE: You'd think we don't need to handle CORS issues, now that we're proxy'ing backend requests
# via /api in the frontend, but the test suite still seems to need it :shrug:
def _add_cors_headers( resp ):
"""Add the necessary headers to a response to allow CORS."""
resp.headers[ "Access-Control-Allow-Origin" ] = "*"

@ -8,13 +8,13 @@ RUN npm install react-scripts@3.2.0 -g
COPY package.json /app/package.json
RUN npm install
COPY . /app/
COPY docker/env /app/.env
ARG ENABLE_TESTS
RUN if [ -n "$ENABLE_TESTS" ]; then echo -e "\nREACT_APP_TEST_MODE=1" >>/app/.env ; fi
RUN npm run build
# create the final target image
FROM nginx:1.17.5-alpine
COPY docker/nginx-default.conf /etc/nginx/conf.d/default.conf
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
CMD [ "nginx", "-g", "daemon off;" ]

@ -1 +0,0 @@
REACT_APP_FLASK_URL = http://localhost:5002

@ -0,0 +1,22 @@
server {
server_name localhost ;
listen 80 ;
location / {
root /usr/share/nginx/html ;
index index.html index.htm ;
}
location /api {
# nb: we access the backend server via the network bridge that docker-compose creates for us
proxy_pass http://flask:5000 ;
rewrite ^/api/(.*) /$1 break ;
}
error_page 500 502 503 504 /50x.html ;
location = /50x.html {
root /usr/share/nginx/html ;
}
}

@ -6509,14 +6509,54 @@
}
},
"http-proxy-middleware": {
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz",
"integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==",
"version": "0.20.0",
"resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.20.0.tgz",
"integrity": "sha512-dNJAk71nEJhPiAczQH9hGvE/MT9kEs+zn2Dh+Hi94PGZe1GluQirC7mw5rdREUtWx6qGS1Gu0bZd4qEAg+REgw==",
"requires": {
"http-proxy": "^1.17.0",
"is-glob": "^4.0.0",
"lodash": "^4.17.11",
"micromatch": "^3.1.10"
"is-glob": "^4.0.1",
"lodash": "^4.17.14",
"micromatch": "^4.0.2"
},
"dependencies": {
"braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"requires": {
"fill-range": "^7.0.1"
}
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"requires": {
"to-regex-range": "^5.0.1"
}
},
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
},
"micromatch": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
"integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==",
"requires": {
"braces": "^3.0.1",
"picomatch": "^2.0.5"
}
},
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"requires": {
"is-number": "^7.0.0"
}
}
}
},
"http-signature": {
@ -9564,6 +9604,11 @@
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
},
"picomatch": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.1.tgz",
"integrity": "sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA=="
},
"pify": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
@ -13382,6 +13427,17 @@
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
"integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w=="
},
"http-proxy-middleware": {
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz",
"integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==",
"requires": {
"http-proxy": "^1.17.0",
"is-glob": "^4.0.0",
"lodash": "^4.17.11",
"micromatch": "^3.1.10"
}
},
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",

@ -6,6 +6,7 @@
"@material-ui/core": "^4.7.0",
"@reach/menu-button": "^0.7.2",
"axios": "^0.19.0",
"http-proxy-middleware": "^0.20.0",
"lodash.clone": "^4.5.0",
"lodash.clonedeep": "^4.5.0",
"react": "^16.11.0",

@ -48,8 +48,14 @@ export default class App extends React.Component
// it's own Flask server, but talks to an existing React server, so we need some way
// for pytest to change which Flask server the React frontend code should tak to.
this._flaskBaseUrl = this.isTestMode() ? this.args._flask : null ;
if ( ! this._flaskBaseUrl )
this._flaskBaseUrl = process.env.REACT_APP_FLASK_URL ;
if ( ! this._flaskBaseUrl ) {
// NOTE: We used to use process.env.REACT_APP_FLASK_URL here, but this means that the client
// needs to have access to the Flask backend server. We now proxy all backend requests via
// "/api/..." endpoints, which we handle ourself (by setupProxy.js for the dev environment,
// and nginx proxying for production), so the client only needs access to the React front-end.
// This also has the nice side-effect of removing CORS issues :-/
this._flaskBaseUrl = "/api" ;
}
}
render() {

@ -0,0 +1,11 @@
const proxy = require( "http-proxy-middleware" ) ;
module.exports = function( app ) {
// proxy all "/api/..." requests to the Flask backend server
// NOTE: This only applies in the dev environment, production requires nginx proxying to be configured.
app.use( "/api", proxy( {
target: process.env.REACT_APP_FLASK_URL,
pathRewrite: { "^/api/": "/" },
changeOrigin: true,
} ) ) ;
}
Loading…
Cancel
Save