Skip to content
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

Rxjs 7.0+ breaking change requires preflight requests for Ajax calls that do not specify crossDomain #6663

Closed
driskell opened this issue Nov 4, 2021 · 3 comments · Fixed by #6710

Comments

@driskell
Copy link

@driskell driskell commented Nov 4, 2021

Bug Report

Current Behavior

In 6.6 crossDomain is true by default, and therefore the X-Requested-With header is not added, and thus a standard Ajax request does not require preflight requests and one's servers do not need to implement support for OPTIONS requests.

Code in 6.6: https://github.com/ReactiveX/rxjs/blob/6.6.7/src/internal/observable/dom/AjaxObservable.ts#L205
The request object is populated at https://github.com/ReactiveX/rxjs/blob/6.6.7/src/internal/observable/dom/AjaxObservable.ts#L181
And this request object contains defaults, so has crossDomain: true.

In 7.0+ crossDomain is still true by default, however, X-Requested-With header is ALWAYS added to ALL requests made by AJAX, regardless, unless crossDomain is explicitly provided as false. This is because the default value of true is missing at the point in time at which the header is added.

Code in 7.4: https://github.com/ReactiveX/rxjs/blob/7.4.0/src/internal/ajax/ajax.ts#L337
The config object is directly from the caller and does not contain defaults because the defaults are not added until later on: https://github.com/ReactiveX/rxjs/blob/7.4.0/src/internal/ajax/ajax.ts#L355

Expected behavior

No preflight request for a standard simple ajax request with no crossDomain option specified (which should default to true)

Reproduction

RxJS 7.4 Codepen: https://codepen.io/Driskell/pen/MWvQymO?editors=1111
RxJS 6.6 Codepen: https://codepen.io/Driskell/pen/yLovOxK?editors=1111

Open console in your browser and click the button. In Safari on macOS you can see on 7.4 preflight response is not successful, but on 6.6 it does not attempt one.

Environment

  • Runtime: Safari, Chrome, etc.
  • RxJS version: 7.0+

Possible Solution

Check if config.crossDomain is defined first, or destructure it with a default on the first line of the function: https://github.com/ReactiveX/rxjs/blob/7.4.0/src/internal/ajax/ajax.ts#L282

Additional context/Screenshots

N/A

@driskell driskell changed the title Rxjs 7.0+ requires preflight requests for all Ajax calls, in comparison to 6.6 Rxjs 7.0+ breaking change requires preflight requests for Ajax calls that do not specify crossDomain Nov 4, 2021
@driskell
Copy link
Author

@driskell driskell commented Nov 30, 2021

@benlesh is it worth pinning the agenda item here? As this is probably the best source of the issue currently encountered and maybe the best starting point for discussion on future of crossDomain.

I have CodePens in here too so it helps reproduce the issue and understand the impacts of the crossDomain parameter and the header that gets added etc.

benlesh added a commit to benlesh/rxjs that referenced this issue Dec 6, 2021
…mers

Fixes an issue where the `crosDomain` flag was being incorrectly reported to users via error objects and response objects as defaulting to `true`, when it was in fact defaulting to `false`.

Deprecates the `crossDomain` flag in favor of allowing the configuration of the request and the browser to dictate whether or not a preflight request is necessary. Adds deprecation messages with advice about how to force CORS preflights. Ultimately, the boolean flag does not make sense, as there are a lot of factors that dictate CORS preflight use and they may vary by browser/environment.

Resolves ReactiveX#6663
benlesh added a commit to benlesh/rxjs that referenced this issue Jan 4, 2022
…mers

Fixes an issue where the `crosDomain` flag was being incorrectly reported to users via error objects and response objects as defaulting to `true`, when it was in fact defaulting to `false`.

Deprecates the `crossDomain` flag in favor of allowing the configuration of the request and the browser to dictate whether or not a preflight request is necessary. Adds deprecation messages with advice about how to force CORS preflights. Ultimately, the boolean flag does not make sense, as there are a lot of factors that dictate CORS preflight use and they may vary by browser/environment.

Resolves ReactiveX#6663
benlesh added a commit that referenced this issue Jan 11, 2022
…mers (#6710)

* fix(ajax): crossDomain flag deprecated and properly reported to consumers

Fixes an issue where the `crosDomain` flag was being incorrectly reported to users via error objects and response objects as defaulting to `true`, when it was in fact defaulting to `false`.

Deprecates the `crossDomain` flag in favor of allowing the configuration of the request and the browser to dictate whether or not a preflight request is necessary. Adds deprecation messages with advice about how to force CORS preflights. Ultimately, the boolean flag does not make sense, as there are a lot of factors that dictate CORS preflight use and they may vary by browser/environment.

Resolves #6663

* chore: Update side effects file

* chore: update side effects files
@driskell
Copy link
Author

@driskell driskell commented Jan 11, 2022

@benlesh Does the PR definitely fix this issue? Looking at the code it seems it tries to resolve the confusion around the flag, but it looks like it will still set the header X-Requested-With with default parameters to AJAX where with 6 it never did. And so it will force all AJAX to be CORS unless the crossDomain is explicitly set, and so still break all code from RxJs 6 that didn’t expect this.

The comment against the crossDomain flag seems strange too - it says don’t use this flag to force a cross domain (I assume it means preflight) and instead set a custom header. But actually the code is setting a custom header if it is set to false. So it doesn’t make any difference what you do you will always get an OPTIONS request sent unless you set this flag which is now deprecated... And in fact to STOP it sending the header you need to set it to true.

@driskell
Copy link
Author

@driskell driskell commented Jan 11, 2022

@benlesh I added a new codepen to reproduce for 7.5.2 and improved it so it shows on screen results, and also added in crossDomain:true case and also default cases for jQuery and axios for comparison.

6.6.7: https://codepen.io/Driskell/pen/yLovOxK
7.4.0: https://codepen.io/Driskell/pen/MWvQymO
7.5.2: https://codepen.io/Driskell/pen/PoJyRaz

In 6.6.7 it works fine and you don't need to specify anything, much like jQuery and Axios. In 7+ and also after 7.5.2 it's still broken unless I specify crossDomain:true.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
1 participant