diff --git a/docs/changelog.md b/docs/changelog.md index 33c59d64..726f728b 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -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)) - 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) +- 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. diff --git a/docs/request.md b/docs/request.md index 6cd03b07..90a172cb 100644 --- a/docs/request.md +++ b/docs/request.md @@ -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.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.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.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`. diff --git a/request/request.js b/request/request.js index 13cdc2c4..54fae64d 100644 --- a/request/request.js +++ b/request/request.js @@ -76,7 +76,7 @@ module.exports = function($window, Promise, oncompletion) { request: makeRequest(function(url, args, resolve, reject) { var method = args.method != null ? args.method.toUpperCase() : "GET" 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 xhr = new $window.XMLHttpRequest(), aborted = false, isTimeout = false @@ -194,7 +194,7 @@ module.exports = function($window, Promise, oncompletion) { if (body == null) xhr.send() 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)) }), jsonp: makeRequest(function(url, args, resolve, reject) { diff --git a/request/tests/test-request.js b/request/tests/test-request.js index 7ff0f2fc..b794a525 100644 --- a/request/tests/test-request.js +++ b/request/tests/test-request.js @@ -212,6 +212,16 @@ o.spec("request", function() { o(data).deepEquals({a: "/items", b: [{x: "y"}]}) }).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) { mock.$defineRoutes({ "GET /item/:x": function(request) { diff --git a/test-utils/xhrMock.js b/test-utils/xhrMock.js index eefbf728..1c9fa1d4 100644 --- a/test-utils/xhrMock.js +++ b/test-utils/xhrMock.js @@ -14,6 +14,7 @@ module.exports = function() { function FormData() {} var $window = { FormData: FormData, + URLSearchParams: URLSearchParams, XMLHttpRequest: function XMLHttpRequest() { var args = {} var headers = {}