Skip to content

Avoid calling allowCrossDomain twice per request #5682

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 1 commit into from
Jun 19, 2019

Conversation

LinusU
Copy link
Contributor

@LinusU LinusU commented Jun 13, 2019

api.use('/', middleware, ...) will end up calling middleware for every request, even if no routers in the ... part matches.

This is because passing a router to express is just like passing any other route handler. The only thing that happens when it doesn't match a route is that it calls next, but by that point, the middleware has already run.

The changes in the PR avoids adding the middleware twice for every route except file upload routes. Which will make express not call allowCrossDomain twice for every incoming request.


Happy to explain more if there's is something unclear, just happened to stumble upon this when debugging a CORS issue...

`api.use('/', middleware, ...)` will end up calling `middleware` for _every_ request, even if no routers in the `...` part matches.

This is because passing a router to express is just like passing any other route handler. The only thing that happens when it doesn't match a route is that it calls `next`, but by that point, the middleware has already run. 

The changes in the PR avoids adding the middleware twice for every route except file upload routes. Which will make express not call `allowCrossDomain` twice for every incoming request.
@codecov
Copy link

codecov bot commented Jun 13, 2019

Codecov Report

Merging #5682 into master will increase coverage by 0.01%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff            @@
##           master   #5682      +/-   ##
=========================================
+ Coverage   94.19%   94.2%   +0.01%     
=========================================
  Files         129     129              
  Lines        9248    9248              
=========================================
+ Hits         8711    8712       +1     
+ Misses        537     536       -1
Impacted Files Coverage Δ
src/ParseServer.js 97.88% <100%> (ø) ⬆️
src/RestWrite.js 93.66% <0%> (+0.17%) ⬆️

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 089b809...f65ea27. Read the comment docs.

@davimacedo
Copy link
Member

Makes sense for me. I am only worried about the public api (https://github.com/parse-community/parse-server/blob/master/src/ParseServer.js#L169) that is currently also accepting cross domain headers. Right?

@LinusU
Copy link
Contributor Author

LinusU commented Jun 14, 2019

[...] that is currently also accepting cross domain headers. Right?

I'm not sure I understand exactly what you mean here 🤔

Both before and after this change the PublicAPIRouter should have CORS headers applied by the middlewares.allowCrossDomain middleware. Should that router not have CORS headers applied?

The new code should be functionally equivalent to the old one. A good way to think about it is in steps:

app.use('/', middleware, router)

// is the same as

app.use('/', middleware)
app.use('/', router)

// is the same as

app.use(middleware)
app.use('/', router)

Thus the very first line using api would apply the CORS middleware to every single route:

api.use(
'/',
middlewares.allowCrossDomain,
new FilesRouter().expressRouter({
maxUploadSize: maxUploadSize,
})
);

as this is the same as:

api.use(middlewares.allowCrossDomain)
api.use('/', new FilesRouter().expressRouter({ maxUploadSize: maxUploadSize }))

@LinusU
Copy link
Contributor Author

LinusU commented Jun 14, 2019

Also, just saw that the FilesRouter will actually also add another CORS middleware 😄

router.post(
'/files/:filename',
Middlewares.allowCrossDomain,
BodyParser.raw({
type: () => {
return true;
},
limit: maxUploadSize,
}), // Allow uploads without Content-Type, or with any Content-Type.
Middlewares.handleParseHeaders,
this.createHandler
);
router.delete(
'/files/:filename',
Middlewares.allowCrossDomain,
Middlewares.handleParseHeaders,
Middlewares.enforceMasterKeyAccess,
this.deleteHandler
);

So I tracked down the introduction of the extra call to this commit:

f23aed5

At that point, the aforementioned cors thing were in place as well, but they are only covering /files/:filename, not e.g. /files. I'm guessing the commit was added to address that, and inadvertently added CORS to every single request.

To be honest, I'm not really sure what the goal here is 😄 If we want CORS headers on every single call, we should add a single api.use(middlewares.allowCrossDomain) where this patch adds them, and then remove all other calls.

If there are only some routes that should have CORS, this call should be moved into the specific file routes instead.

As the code works right now, CORS is applied to every single request.

I'd be happy to submit a patch for either way...

@davimacedo
Copy link
Member

I think that CORS should be applied to all requests except PublicAPIRouter. @acinader @dplewis do you agree?

@acinader
Copy link
Contributor

  1. this patch looks good to me
  2. I think the public api needs cors for stuff like this: https://github.com/parse-community/parse-server/blob/master/src/Routers/PublicAPIRouter.js#L203, right?

@davimacedo
Copy link
Member

I think req.xhr will work without cors if the script is running on a page in the same domain. But anyway the public api is running with cors for a long while and changing this will probably break some apps. So let's keep the PR how it is and merge.

@davimacedo davimacedo merged commit 922251a into parse-community:master Jun 19, 2019
@LinusU LinusU deleted the patch-1 branch June 20, 2019 06:22
@LinusU
Copy link
Contributor Author

LinusU commented Jun 20, 2019

Nice, I'll submit a follow up PR to remove some more redundant invocations as well 👍

UnderratedDev pushed a commit to UnderratedDev/parse-server that referenced this pull request Mar 21, 2020
)

`api.use('/', middleware, ...)` will end up calling `middleware` for _every_ request, even if no routers in the `...` part matches.

This is because passing a router to express is just like passing any other route handler. The only thing that happens when it doesn't match a route is that it calls `next`, but by that point, the middleware has already run. 

The changes in the PR avoids adding the middleware twice for every route except file upload routes. Which will make express not call `allowCrossDomain` twice for every incoming request.
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