New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proxy ElasticSearch service #868
Conversation
Fixes #630 Includes: * Add middleware to Express server to proxy ElasticSearch requests * Allow only GET and POST requests to a known path * Add new config entry for index (*i.e.*, ElasticSearch) URL, backed by an environment variable * Add environment variable to the necessary spots to ensure it is properly fixed at build time (per README) * Handle a FIXME in server.js, preferring `.find()` over `.forEach()`
docker build -t ld4p/sinopia_editor:dev --build-arg TRELLIS_BASE_URL=$TRELLIS_BASE_URL_DEV --build-arg SINOPIA_URI=$SINOPIA_URI_DEV --build-arg AWS_COGNITO_DOMAIN=$AWS_COGNITO_DOMAIN_DEV --build-arg COGNITO_CLIENT_ID=$COGNITO_CLIENT_ID_DEV --build-arg COGNITO_USER_POOL_ID=$COGNITO_USER_POOL_ID_DEV . | ||
docker build -t ld4p/sinopia_editor:stage --build-arg TRELLIS_BASE_URL=$TRELLIS_BASE_URL_STAGE --build-arg SINOPIA_URI=$SINOPIA_URI_STAGE --build-arg AWS_COGNITO_DOMAIN=$AWS_COGNITO_DOMAIN_STAGE --build-arg COGNITO_CLIENT_ID=$COGNITO_CLIENT_ID_STAGE --build-arg COGNITO_USER_POOL_ID=$COGNITO_USER_POOL_ID_STAGE . | ||
docker build -t ld4p/sinopia_editor:prod --build-arg TRELLIS_BASE_URL=$TRELLIS_BASE_URL_PROD --build-arg SINOPIA_URI=$SINOPIA_URI_PROD --build-arg AWS_COGNITO_DOMAIN=$AWS_COGNITO_DOMAIN_PROD --build-arg COGNITO_CLIENT_ID=$COGNITO_CLIENT_ID_PROD --build-arg COGNITO_USER_POOL_ID=$COGNITO_USER_POOL_ID_PROD . | ||
docker build -t ld4p/sinopia_editor:dev --build-arg TRELLIS_BASE_URL=$TRELLIS_BASE_URL_DEV --build-arg SINOPIA_URI=$SINOPIA_URI_DEV --build-arg AWS_COGNITO_DOMAIN=$AWS_COGNITO_DOMAIN_DEV --build-arg COGNITO_CLIENT_ID=$COGNITO_CLIENT_ID_DEV --build-arg COGNITO_USER_POOL_ID=$COGNITO_USER_POOL_ID_DEV --build-arg INDEX_URL=$INDEX_URL_DEV . |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI, I have already tracked down these values and added new env-specific variables to the CircleCI build.
@@ -116,6 +116,7 @@ | |||
"react-router-dom": "^4.3.1", | |||
"redux": "^4.0.1", | |||
"redux-thunk": "^2.3.0", | |||
"request": "^2.88.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems in Javascriptland there are a million options here, and it's not clear to me which is the best fit or the most idiomatic. Happy to consider alternatives.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This module request
is fine.
app.use(express.json()) | ||
|
||
app.use('/api/search', (req, res) => { | ||
if (!['GET', 'POST'].includes(req.method)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We only allow the editor to hit the search part of ElasticSearch's API, which means either GET or POST could be used. Throw a 400 error if any other HTTP action is attempted.
|
||
// Hard-coded for now since we only have the one use case for proxying ES, | ||
// i.e., full-text search of resources | ||
if (req.path !== '/sinopia_resources/sinopia/_search') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't love this approach but I was loath to get into regex or otherwise parsing the request path, lest I leave some wrinkle that could be exploited. I am open to validating requests some other way, to prevent our ElasticSearch instance from getting owned or hosed.
const versoSpoof = require('./src/versoSpoof') | ||
|
||
const port = 8000 | ||
const app = express() | ||
|
||
app.use(express.static(`${__dirname}/`)) | ||
// Required for ElasticSearch proxy middleware to parse response body as JSON |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that server.js
doesn't have test coverage. I'm not sure exactly how or what I'd test. I could consider extracting the middleware elsewhere so it's easier to test but that's not super clear to me at the moment.
Hi @mjgiarlo, I am getting this error both when I rebuild the Editor container and try to run with sinopia_editor/src/Config.js:109
export default Config
^^^^^^
SyntaxError: Unexpected token export I'm hoping this my user error :-). |
@jermnelson That does not ring a bell. Weird! Happy to pair in the morning. |
} | ||
}) | ||
res.status(200).type('application/json').send(json) | ||
const json = versoSpoof.owlOntUrl2JsonMappings.find(el => reqUri === el.url).json |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
huzzah for getting rid of FIXME. 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🕺
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM; I have a couple of questions
}) | ||
|
||
app.use(express.static(`${__dirname}/`)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't get what this line is doing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ndushay This middleware is for serving static assets to the browser, such as the stuff in src/styles/
and static/
. I'm not sure how "right" this code is given how we're using it, tbh, and I didn't add it—it was shifted around by my work. This code was added 4 years ago by LC: fb13bb2#diff-dc2704ac83baf8775944bab1251b45abR9
If we think we should tighten up how we serve static assets... new issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how about just adding a comment:
//serve static assets to the browser, e.g. from src/styles/ and static/
And mayhaps making a ticket to move "styles" out of "src" directory??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was/am hoping someone with more knowledge of express could write up the ticket. I'm reluctant to pile that on the backlog without a clearer sense of the problem or the solution. (Sorry, still recovering from Hyrax backlog stress, where anyone and everyone tossed issues that were ill defined and often just questions.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok. I can live w/o the ticket, but would appreciate the comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ndushay ok.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
res.status(200).type('application/json').send(json) | ||
const json = versoSpoof.owlOntUrl2JsonMappings.find(el => reqUri === el.url).json | ||
|
||
res.json(json) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you say more about this line vs old line 43 ? is status 200 the default? Is application/json the default type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ndushay Oh, shoot, I meant to leave a comment about this line but missed it. Sorry! Sure.
We can safely shorten res.status(200).type('application/json').send(json)
to res.json(json)
because Express will return an HTTP 200 OK by default, and calling .json()
automatically sets the content type (to application/json
), sends the content to the client, and ends the request/response cycle.
Else the server will not start because src/Config.js uses ES6 and by default npm will use node vs. babel-node when running npm start.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM; merging.
Fixes #630
Includes:
.find()
over.forEach()