Skip to content

Validate serverURL on Start #4204

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

Merged
merged 7 commits into from
Oct 17, 2017

Conversation

montymxb
Copy link
Contributor

Specifically this adds validation for publicServerUrl, if the value is present. This will attempt to grab the /health endpoint, expecting a 200 code and OK body, if it doesn't receive this it will spit out something like.

...
[1234] parse-server running on http://localhost:1337/parse

WARNING, Unable to connect to publicServerURL 'http://localhost:1337/oops'. Cloud code and push notifications may be unavailable!

This does not add tests yet as I wanted to field the positioning (and wording) of this before I proceed. There may be other systems that would be affected besides cloud code and push.

If this looks ok as is I'll rework it so we can get test coverage on this.

@@ -373,6 +373,7 @@ class ParseServer {
if (process.env.PARSE_SERVER_ENABLE_EXPERIMENTAL_DIRECT_ACCESS === '1') {
Parse.CoreManager.setRESTController(ParseServerRESTController(appId, appRouter));
}
this.verifyServerUrl(_ref2.publicServerURL);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_ref2 ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also? You probably need to add a delay, at least a process.nextTick as the app is not mounted/ not listening yet on the port.

Not sure if we can get that event from Express, i’ll Have a look!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be ideal to have it execute after an event! As for _ref2, yeah that's gonna get changed before this can be seriously considered, I can't remember where I pulled that from...

Beyond that is this acceptable to put in ParseServer.js or do you think it would be more appropriate elsewhere?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That’s an excellent place to put it, makes total sense. About the event, I may have been mistaken, perhaps we should wait for the ‘mount’ event, not sure if we can have access to the server that listens in the end. Best chance may be a check after 2s no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We would have to catch when express was listening, but that object is a bit high up. We could do a timing check but I wish we could just get the event. I'll look around a bit more and see if there's anything else, if not we can always do the delay.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do think we can just listen on the api constructed there, it's later returned, and comes back to be listened under whatever the mount path is, under another express instance. I believe when the first one has listen called on it, it will chain down, and we'll get our listening callback as expected; without being too far ahead.

Looks like it's used in ParseWebSocketServer as such,

...
wss.on('listening', () => {
    logger.info('Parse LiveQuery Server starts running');
});

@flovilmart
Copy link
Contributor

Perhaps check the listening event: https://nodejs.org/api/net.html#net_event_listening

Should be available/ fired on the app :)

app.on(‘listening’, () => { verifyServerURL() })

@montymxb
Copy link
Contributor Author

montymxb commented Sep 23, 2017

The event sounds much better than sleeping/waiting for a bit, I'll rework this to fire from that, and address that improper var reference.

@montymxb
Copy link
Contributor Author

Doh! I wrote in _ref2 as I was looking at the compiled lib code at that moment, it's a totally garbage value, oops.

this.verifyServerUrl(_ref2.publicServerURL);

const AppCache = require('./cache');
var serverUrl = AppCache.AppCache.cache[appId]['value']['publicServerURL'];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or just Parse.serverURL ;)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be much better

setTimeout(function() {
if(serverUrl) {
const request = require('request');
request(serverUrl.replace(/\/$/, "") + "/health", function (error, response, body) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you could use Parse._request probably this way you don't even need those replacements.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I'll look to see if that'll swap out ok.

Copy link
Contributor

@acinader acinader left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a) love this. thank you
b) ugh, I've become THAT guy™

@@ -0,0 +1,32 @@
"use strict";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use ' instead of " there are a few places.

/* Tests for ParseServer.js */
var express = require('express');

import ParseServer from '../src/ParseServer';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove extra white space

import ParseServer from '../src/ParseServer';

var app = express();
//app.use(bodyParser.json({ 'type': '*/*' }));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove commented out code.

it("validate good publicServerUrl", (done) => {
ParseServer.verifyServerUrl('http://localhost:12345', function(result) {
if(!result) {
jfail('Did not pass valid url');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using jfail is fine. we've moved to using done.fail() just for future reference.

@@ -373,6 +373,11 @@ class ParseServer {
if (process.env.PARSE_SERVER_ENABLE_EXPERIMENTAL_DIRECT_ACCESS === '1') {
Parse.CoreManager.setRESTController(ParseServerRESTController(appId, appRouter));
}

const AppCache = require('./cache');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

requires at the top please.

request(serverUrl.replace(/\/$/, "") + "/health", function (error, response, body) {
if (error || response.statusCode !== 200 || body !== "OK") {
// eslint-disable-next-line
console.warn("\nWARNING, Unable to connect to publicServerURL '" + serverUrl + "'. Cloud code and push notifications may be unavailable!\n");
Copy link
Contributor

@acinader acinader Sep 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use template

`${a-var} blah`

break the code for the comment onto two lines (not the comment).

console.warn(`\nWARNING, Unable to ... \'${serverUrl}\'.  Cloud code and ....` +
    'blah blah blah');
   
remove the // eslint-disable

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally valid nits. I've made the changes locally but I'm still fiddling with something else before I push changes up.

Copy link
Contributor Author

@montymxb montymxb Sep 26, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@acinader as for the disable on lint, console statements don't look to be allowed. Ending up with Unexpected console statement no-console. If you take a look you'll see that others have run into the same issue and ignored their console calls as well.

If there's some alternative approach I'm not aware of let me know, but that seems about right.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following up on that something like /* eslint-disable no-console */ may be more appropriate than just a flat out disable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, yeah. the logger isn't available here. so yes, adding the error your targeting (no-console) is the right call see around line 225 where console is used.

@codecov
Copy link

codecov bot commented Sep 26, 2017

Codecov Report

Merging #4204 into master will decrease coverage by 0.01%.
The diff coverage is 81.81%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #4204      +/-   ##
==========================================
- Coverage   92.22%   92.21%   -0.02%     
==========================================
  Files         116      116              
  Lines        8092     8103      +11     
==========================================
+ Hits         7463     7472       +9     
- Misses        629      631       +2
Impacted Files Coverage Δ
src/ParseServer.js 88.3% <81.81%> (-0.45%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 6eed955...b8b44f8. Read the comment docs.

@montymxb
Copy link
Contributor Author

montymxb commented Sep 26, 2017

Just need to adjust the port I'm listening to for testing. I'm verifying the entire suite locally before I push this up again.

acinader
acinader previously approved these changes Sep 26, 2017
Copy link
Contributor

@acinader acinader left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

https://hackernoon.com/why-you-shouldnt-use-var-anymore-f109a58b9b70

is a good write-up on why to use let (and ideally const) instead of var.

@montymxb
Copy link
Contributor Author

Thanks @acinader , you'll have to forgive me I'm a bit rusty with my js on node at the moment. Using let/const makes sense over var. I'll go back over those and make the appropriate changes.

@flovilmart I believe things are almost good on my end here (minus the var changes I'll be putting up) . Let me know if there's anything in particular that still requires attention.

As for the failure I'm seeing quite a few of these 'open connection...' errors. At first I thought it had something to do with my using reconfigureServer in the first set of changes. Looks to be that those issues are persisting beyond that, and they seem to be inconsistent, unless I'm missing something that's still changed within these tests. I'm running some more tests locally, and have been seeing intermittent passes/fails on this branch, all regarding the same open connection issue. I haven't confirmed that this happens on the master yet. We may want to hold here until I can confirm there's not some subtle issue being introduced by this.

…ication call into app.on('mount') callback, removed setTimeout from verification.
@montymxb
Copy link
Contributor Author

montymxb commented Sep 26, 2017

So I believe I have found the issue, but we'll see for sure once these tests are done.

It appears that running the url verification actually breaks quite a few tests, but only if the connection that is made is still open when a given tests completes, particularly those that use reconfigureServer. This gave the appearance of a random failure, but was most definitely being caused by this additional check after going over things.

To fix this I changed a couple points, one to move the verification call under a conditional that is only executed when not in a testing environment, and two to wrap said call within a mount callback (instead of a fixed timeout). The mount callback is fired directly after this express instance is mounted under another parent instance.

Although the parent is not listening yet, it is assumed it will be before we have the chance to time out (likely to be milliseconds behind). Checking this locally it looks to work just fine. If for some reason it misses this won't cause anything to not run, just would give an eroneous warning. If that ends up being the case in some production instances we could always safely modify this further to be a bit more patient in waiting for a response post-mount.

Those changes looks like so:

// run the following when not testing
if (!process.env.TESTING) {
   ...
   ...
   ...
   
  // verify the server url after a 'mount' event is received
  api.on('mount', function() {
	ParseServer.verifyServerUrl();
  });
}

Since the verification is called separately during testing it is still covered, but now it's out of the way of interfering with the expected behavior of other tests. The only thing not covered being the bit that's inside the conditional above of course, I'm thinking the coverage diff will still be a positive.

Also changed a couple declarations using var to const.

::edit::
The diff is not quite up to snuff, but the tests are now good.

@montymxb montymxb requested a review from flovilmart September 26, 2017 19:49
@flovilmart flovilmart merged commit 9376b4d into parse-community:master Oct 17, 2017
@montymxb montymxb deleted the url-health-check branch October 24, 2017 20:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants