Send URLSearchParams as request body without extra configuration (#2695)

This commit is contained in:
James Cote 2022-01-31 04:12:02 -05:00 committed by GitHub
parent ab4b21dacc
commit 99c6d813d2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 15 additions and 3 deletions

View file

@ -39,6 +39,7 @@ PSA: changes to [`mithril/stream`](stream.md) are now specified in this changelo
- Allow Mithril to be loaded in non-browser environments without modification. ([#2633](https://github.com/MithrilJS/mithril.js/pull/2633) [@isiahmeadows](https://github.com/isiahmeadows)) - Allow Mithril to be loaded in non-browser environments without modification. ([#2633](https://github.com/MithrilJS/mithril.js/pull/2633) [@isiahmeadows](https://github.com/isiahmeadows))
- Work around a bundler bug that corrupted RegExps [#2647](https://github.com/MithrilJS/mithril.js/issues/) ([#2655](https://github.com/MithrilJS/mithril.js/pull/2655)) - Work around a bundler bug that corrupted RegExps [#2647](https://github.com/MithrilJS/mithril.js/issues/) ([#2655](https://github.com/MithrilJS/mithril.js/pull/2655))
- Adapt handling of no content (204) responses to match XHR Spec ([#2624](https://github.com/MithrilJS/mithril.js/pull/2641)) [@Evoke-PHP](https://github.com/Evoke-PHP) - Adapt handling of no content (204) responses to match XHR Spec ([#2624](https://github.com/MithrilJS/mithril.js/pull/2641)) [@Evoke-PHP](https://github.com/Evoke-PHP)
- Add `URLSearchParams` support to `m.request` ([#2695](https://github.com/MithrilJS/mithril.js/pull/2695) [@Coteh](https://github.com/Coteh))
Important note: if you were using any of these undocumented tools, they are no longer available as of this release. This is not considered a breaking change as they were written for internal usage and as of v2 are all 100% unsupported in userland. Important note: if you were using any of these undocumented tools, they are no longer available as of this release. This is not considered a breaking change as they were written for internal usage and as of v2 are all 100% unsupported in userland.

View file

@ -57,7 +57,7 @@ Argument | Type | Required | Descr
`options.config` | `xhr = Function(xhr)` | No | Exposes the underlying XMLHttpRequest object for low-level configuration and optional replacement (by returning a new XHR). `options.config` | `xhr = Function(xhr)` | No | Exposes the underlying XMLHttpRequest object for low-level configuration and optional replacement (by returning a new XHR).
`options.headers` | `Object` | No | Headers to append to the request before sending it (applied right before `options.config`). `options.headers` | `Object` | No | Headers to append to the request before sending it (applied right before `options.config`).
`options.type` | `any = Function(any)` | No | A constructor to be applied to each object in the response. Defaults to the [identity function](https://en.wikipedia.org/wiki/Identity_function). `options.type` | `any = Function(any)` | No | A constructor to be applied to each object in the response. Defaults to the [identity function](https://en.wikipedia.org/wiki/Identity_function).
`options.serialize` | `string = Function(any)` | No | A serialization method to be applied to `body`. Defaults to `JSON.stringify`, or if `options.body` is an instance of [`FormData`](https://developer.mozilla.org/en/docs/Web/API/FormData), defaults to the [identity function](https://en.wikipedia.org/wiki/Identity_function) (i.e. `function(value) {return value}`). `options.serialize` | `string = Function(any)` | No | A serialization method to be applied to `body`. Defaults to `JSON.stringify`, or if `options.body` is an instance of [`FormData`](https://developer.mozilla.org/en/docs/Web/API/FormData) or [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams), defaults to the [identity function](https://en.wikipedia.org/wiki/Identity_function) (i.e. `function(value) {return value}`).
`options.deserialize` | `any = Function(any)` | No | A deserialization method to be applied to the `xhr.response` or normalized `xhr.responseText`. Defaults to the [identity function](https://en.wikipedia.org/wiki/Identity_function). If `extract` is defined, `deserialize` will be skipped. `options.deserialize` | `any = Function(any)` | No | A deserialization method to be applied to the `xhr.response` or normalized `xhr.responseText`. Defaults to the [identity function](https://en.wikipedia.org/wiki/Identity_function). If `extract` is defined, `deserialize` will be skipped.
`options.extract` | `any = Function(xhr, options)` | No | A hook to specify how the XMLHttpRequest response should be read. Useful for processing response data, reading headers and cookies. By default this is a function that returns `options.deserialize(parsedResponse)`, throwing an exception when the server response status code indicates an error or when the response is syntactically invalid. If a custom `extract` callback is provided, the `xhr` parameter is the XMLHttpRequest instance used for the request, and `options` is the object that was passed to the `m.request` call. Additionally, `deserialize` will be skipped and the value returned from the extract callback will be left as-is when the promise resolves. `options.extract` | `any = Function(xhr, options)` | No | A hook to specify how the XMLHttpRequest response should be read. Useful for processing response data, reading headers and cookies. By default this is a function that returns `options.deserialize(parsedResponse)`, throwing an exception when the server response status code indicates an error or when the response is syntactically invalid. If a custom `extract` callback is provided, the `xhr` parameter is the XMLHttpRequest instance used for the request, and `options` is the object that was passed to the `m.request` call. Additionally, `deserialize` will be skipped and the value returned from the extract callback will be left as-is when the promise resolves.
`options.background` | `Boolean` | No | If `false`, redraws mounted components upon completion of the request. If `true`, it does not. Defaults to `false`. `options.background` | `Boolean` | No | If `false`, redraws mounted components upon completion of the request. If `true`, it does not. Defaults to `false`.

View file

@ -76,7 +76,7 @@ module.exports = function($window, Promise, oncompletion) {
request: makeRequest(function(url, args, resolve, reject) { request: makeRequest(function(url, args, resolve, reject) {
var method = args.method != null ? args.method.toUpperCase() : "GET" var method = args.method != null ? args.method.toUpperCase() : "GET"
var body = args.body var body = args.body
var assumeJSON = (args.serialize == null || args.serialize === JSON.serialize) && !(body instanceof $window.FormData) var assumeJSON = (args.serialize == null || args.serialize === JSON.serialize) && !(body instanceof $window.FormData || body instanceof $window.URLSearchParams)
var responseType = args.responseType || (typeof args.extract === "function" ? "" : "json") var responseType = args.responseType || (typeof args.extract === "function" ? "" : "json")
var xhr = new $window.XMLHttpRequest(), aborted = false, isTimeout = false var xhr = new $window.XMLHttpRequest(), aborted = false, isTimeout = false
@ -194,7 +194,7 @@ module.exports = function($window, Promise, oncompletion) {
if (body == null) xhr.send() if (body == null) xhr.send()
else if (typeof args.serialize === "function") xhr.send(args.serialize(body)) else if (typeof args.serialize === "function") xhr.send(args.serialize(body))
else if (body instanceof $window.FormData) xhr.send(body) else if (body instanceof $window.FormData || body instanceof $window.URLSearchParams) xhr.send(body)
else xhr.send(JSON.stringify(body)) else xhr.send(JSON.stringify(body))
}), }),
jsonp: makeRequest(function(url, args, resolve, reject) { jsonp: makeRequest(function(url, args, resolve, reject) {

View file

@ -212,6 +212,16 @@ o.spec("request", function() {
o(data).deepEquals({a: "/items", b: [{x: "y"}]}) o(data).deepEquals({a: "/items", b: [{x: "y"}]})
}).then(done) }).then(done)
}) })
o("works w/ URLSearchParams body", function(done) {
mock.$defineRoutes({
"POST /item": function(request) {
return {status: 200, responseText: JSON.stringify({a: request.url, b: request.body.toString()})}
}
})
request({method: "POST", url: "/item", body: new URLSearchParams({x: "y", z: "w"})}).then(function(data) {
o(data).deepEquals({a: "/item", b: "x=y&z=w"})
}).then(done)
});
o("ignores unresolved parameter via GET", function(done) { o("ignores unresolved parameter via GET", function(done) {
mock.$defineRoutes({ mock.$defineRoutes({
"GET /item/:x": function(request) { "GET /item/:x": function(request) {

View file

@ -14,6 +14,7 @@ module.exports = function() {
function FormData() {} function FormData() {}
var $window = { var $window = {
FormData: FormData, FormData: FormData,
URLSearchParams: URLSearchParams,
XMLHttpRequest: function XMLHttpRequest() { XMLHttpRequest: function XMLHttpRequest() {
var args = {} var args = {}
var headers = {} var headers = {}