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

Ajax: Support binary data (including FormData) #5197

Merged
merged 1 commit into from
Feb 1, 2023

Conversation

mgol
Copy link
Member

@mgol mgol commented Jan 16, 2023

Summary

NOTE: Please don't review the first commit; that one is #5196, it was just easier for me to depend on it. (that PR landed)

Two changes have been applied:

  • prefilters are now applied before data is converted to a string;
    this allows prefilters to disable such a conversion
  • a prefilter for binary data is added; it disables data conversion
    for non-string non-plain-object data; for FormData bodies, it
    removes manually-set Content-Type header - this is required
    as browsers need to append their own boundary to the header

Ref gh-4150

+39 bytes. We should discuss whether we want this fully in core or just the small change of running prefilters early enough for this to be possible. It is quite generic, though, with the small exception of special FormData treatment - which, I think, is not necessarily desired in all cases? Unless it is - then the PR overhead would be +20 bytes instead of +39.

Checklist

@mgol mgol added Ajax Needs review Discuss in Meeting Reserved for Issues and PRs that anyone would like to discuss in the weekly meeting. labels Jan 16, 2023
@mgol mgol added this to the 4.0.0 milestone Jan 16, 2023
@mgol mgol self-assigned this Jan 16, 2023
@mgol mgol force-pushed the ajax-prefilters-before-data-gh-4150 branch from 3584c0b to 909c466 Compare January 16, 2023 13:51
Comment on lines +565 to -571
// Apply prefilters
inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );

// Convert data if not already a string
if ( s.data && s.processData && typeof s.data !== "string" ) {
s.data = jQuery.param( s.data, s.traditional );
}

// Apply prefilters
inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
Copy link
Member

Choose a reason for hiding this comment

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

I think moving prefilters ahead of string coercion is a breaking change with respect to custom prefilters, cf. https://api.jquery.com/jQuery.ajaxPrefilter/ (emphasis mine):

originalOptions are the options as provided to the $.ajax() method, unmodified and, thus, without defaults from ajaxSettings

Is there a way to instead establish something like prefilter phases?

Copy link
Member Author

Choose a reason for hiding this comment

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

The line that now happens after the prefilters is only setting data, not options. Is there any change that I'm missing?

BTW, I would also consider this a breaking change regardless of the above, that's why I'm targeting it at v4.

@timmywil timmywil removed the Discuss in Meeting Reserved for Issues and PRs that anyone would like to discuss in the weekly meeting. label Jan 23, 2023
Copy link
Member

@timmywil timmywil left a comment

Choose a reason for hiding this comment

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

Good for 4.0. Might need a note in docs about the prefilter going before stringifying s.data, if that was ever documented.

// `Content-Type` for requests with `FormData` bodies needs to be set
// by the browser as it needs to append the `boundary` it generated.
if ( s.data instanceof window.FormData ) {
s.contentType = false;
Copy link
Member Author

Choose a reason for hiding this comment

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

Note to self: check if this could be overridden in options if this is set to false for all binary data, not just FormData.

Copy link
Member Author

@mgol mgol Feb 8, 2023

Choose a reason for hiding this comment

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

OK, this cannot be changed via settings as of now. 😕 I'll need another patch, I think.

Copy link
Member Author

Choose a reason for hiding this comment

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

PR: #5205

Two changes have been applied:
* prefilters are now applied before data is converted to a string;
  this allows prefilters to disable such a conversion
* a prefilter for binary data is added; it disables data conversion
  for non-string non-plain-object `data`; for `FormData` bodies, it
  removes manually-set `Content-Type` header - this is required
  as browsers need to append their own boundary to the header

Ref jquerygh-4150
@mgol mgol force-pushed the ajax-prefilters-before-data-gh-4150 branch from 909c466 to 5e8fc4d Compare January 23, 2023 23:51
@mgol mgol merged commit a7ed9a7 into jquery:main Feb 1, 2023
@mgol mgol removed the Needs review label Feb 1, 2023
@mgol mgol deleted the ajax-prefilters-before-data-gh-4150 branch February 1, 2023 12:48
mgol added a commit to mgol/jquery that referenced this pull request Feb 6, 2023
PR jquerygh-5197 started treating all non-string non-plain-object
`data` values as binary. However, `jQuery.ajax` also supports
arrays as values of `data`. This change makes regular arrays
no longer be considered binary data.

Surprisingly, we had no tests for array `data` values; otherwise,
we'd detect the issue earlier. This change also adds
a few such missing tests.

Ref jquerygh-5197
@mgol mgol mentioned this pull request Feb 6, 2023
2 tasks
@mgol
Copy link
Member Author

mgol commented Feb 6, 2023

I missed handling array data values; a fix at #5203.

mgol added a commit to mgol/jquery that referenced this pull request Feb 8, 2023
The way jquerygh-5197 implemented binary data handling, `processData`
was being explicitly set to `false`. This is expected but it made
it impossible to override it to `true`. The new logic will only
set `processData` to `false` if it wasn't explicitly passed
in original options.

Ref jquerygh-5197
mgol added a commit that referenced this pull request Mar 20, 2023
The way gh-5197 implemented binary data handling, `processData`
was being explicitly set to `false`. This is expected but it made
it impossible to override it to `true`. The new logic will only
set `processData` to `false` if it wasn't explicitly passed
in original options.

Closes gh-5205
Ref gh-5197
mgol added a commit to mgol/jquery that referenced this pull request Mar 20, 2023
PR jquerygh-5197 started treating all non-string non-plain-object
`data` values as binary. However, `jQuery.ajax` also supports
arrays as values of `data`. This change makes regular arrays
no longer be considered binary data.

Surprisingly, we had no tests for array `data` values; otherwise,
we'd detect the issue earlier. This change also adds
a few such missing tests.

Ref jquerygh-5197
mgol added a commit that referenced this pull request Mar 20, 2023
PR gh-5197 started treating all non-string non-plain-object
`data` values as binary. However, `jQuery.ajax` also supports
arrays as values of `data`. This change makes regular arrays
no longer be considered binary data.

Surprisingly, we had no tests for array `data` values; otherwise,
we'd detect the issue earlier. This change also adds
a few such missing tests.

Closes gh-5203
Ref gh-5197
mgol added a commit that referenced this pull request Mar 20, 2023
PR gh-5197 started treating all non-string non-plain-object
`data` values as binary. However, `jQuery.ajax` also supports
arrays as values of `data`. This change didn't land on `3.x-stable`;
however... Surprisingly, we had no tests for array `data` values.
This change backports a few such missing tests added in gh-5203.

Ref gh-5197
Ref gh-5203
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

3 participants