From bb54a3b675b00519876c0a49973bf2d340e6ce3d Mon Sep 17 00:00:00 2001 From: Leo Horie Date: Sat, 19 Apr 2014 22:47:03 -0400 Subject: [PATCH] add extract option to m.request --- archive/v0.1.9/mithril-tests.js | 3 ++- archive/v0.1.9/mithril.js | 3 ++- archive/v0.1.9/mithril.min.js | 2 +- archive/v0.1.9/mithril.min.map | 2 +- archive/v0.1.9/mithril.min.zip | Bin 38736 -> 38945 bytes archive/v0.1.9/mithril.request.html | 26 +++++++++++++++++----- docs/mithril.request.md | 33 +++++++++++++++++++++++----- mithril.js | 3 ++- 8 files changed, 56 insertions(+), 16 deletions(-) diff --git a/archive/v0.1.9/mithril-tests.js b/archive/v0.1.9/mithril-tests.js index 7d1a45d2..e156708e 100644 --- a/archive/v0.1.9/mithril-tests.js +++ b/archive/v0.1.9/mithril-tests.js @@ -430,11 +430,12 @@ Mithril = m = new function app(window) { var deferred = m.deferred() var serialize = xhrOptions.serialize || JSON.stringify var deserialize = xhrOptions.deserialize || JSON.parse + var extract = xhrOptions.extract || function(xhr, xhrOptions) {return xhr.responseText} xhrOptions.url = parameterizeUrl(xhrOptions.url, xhrOptions.data) xhrOptions = bindData(xhrOptions, xhrOptions.data, serialize) xhrOptions.onload = xhrOptions.onerror = function(e) { var unwrap = (e.type == "load" ? xhrOptions.unwrapSuccess : xhrOptions.unwrapError) || identity - var response = unwrap(deserialize(e.target.responseText)) + var response = unwrap(deserialize(extract(e.target, xhrOptions))) if (response instanceof Array && xhrOptions.type) { for (var i = 0; i < response.length; i++) response[i] = new xhrOptions.type(response[i]) } diff --git a/archive/v0.1.9/mithril.js b/archive/v0.1.9/mithril.js index 91aa2e83..d9b1cce7 100644 --- a/archive/v0.1.9/mithril.js +++ b/archive/v0.1.9/mithril.js @@ -430,11 +430,12 @@ Mithril = m = new function app(window) { var deferred = m.deferred() var serialize = xhrOptions.serialize || JSON.stringify var deserialize = xhrOptions.deserialize || JSON.parse + var extract = xhrOptions.extract || function(xhr, xhrOptions) {return xhr.responseText} xhrOptions.url = parameterizeUrl(xhrOptions.url, xhrOptions.data) xhrOptions = bindData(xhrOptions, xhrOptions.data, serialize) xhrOptions.onload = xhrOptions.onerror = function(e) { var unwrap = (e.type == "load" ? xhrOptions.unwrapSuccess : xhrOptions.unwrapError) || identity - var response = unwrap(deserialize(e.target.responseText)) + var response = unwrap(deserialize(extract(e.target, xhrOptions))) if (response instanceof Array && xhrOptions.type) { for (var i = 0; i < response.length; i++) response[i] = new xhrOptions.type(response[i]) } diff --git a/archive/v0.1.9/mithril.min.js b/archive/v0.1.9/mithril.min.js index a8a32e92..6575620f 100644 --- a/archive/v0.1.9/mithril.min.js +++ b/archive/v0.1.9/mithril.min.js @@ -4,5 +4,5 @@ http://github.com/lhorie/mithril.js (c) Leo Horie License: MIT */ -Mithril=m=new function(a){function b(){var a=arguments,b="[object Object]"==u.call(a[1]),c=b?a[1]:{},d="class"in c?"class":"className",e=t[a[0]];if(void 0===e){t[a[0]]=e={tag:"div",attrs:{}};for(var f,h=[];f=v.exec(a[0]);)if(""==f[1])e.tag=f[2];else if("#"==f[1])e.attrs.id=f[2];else if("."==f[1])h.push(f[2]);else if("["==f[3][0]){var i=w.exec(f[3]);e.attrs[i[1]]=i[3]||!0}h.length>0&&(e.attrs[d]=h.join(" "))}e=g(e),e.attrs=g(e.attrs),e.children=b?a[2]:a[1];for(var j in c)e.attrs[j]=j==d?(e.attrs[j]||"")+" "+c[j]:c[j];return e}function c(b,g,h,i,j,k){if(null===g||void 0===g)return void(h&&e(h.nodes));if("retain"!==g.subtree){var l=u.call(h),m=u.call(g);if(l!=m&&(null!==h&&void 0!==h&&e(h.nodes),h=new g.constructor,h.nodes=[]),"[object Array]"==m){for(var n=[],o=h.length===g.length,p=0,q=0;q-1?new g.constructor(g):g,h.nodes=[s];else if(h.valueOf()!==g.valueOf()||i===!0){if(g.$trusted){var v=h.nodes[0],n=[v];if(v){for(;v=v.nextSibling;)n.push(v);e(n),s=f(b,j,g)}else b.innerHTML=g}else s=h.nodes[0],b.insertBefore(s,b.childNodes[j]||null),s.nodeValue=g;h=new g.constructor(g),h.nodes=[s]}else h.nodes.intact=!0}return h}}function d(b,c,d,e){for(var f in c){var g=c[f],i=d[f];if(!(f in d)||i!==g||b===a.document.activeElement){if(d[f]=g,"config"===f)continue;if("function"==typeof g&&0==f.indexOf("on"))b[f]=h(g,b);else if("style"===f)for(var j in g)(void 0===i||i[j]!==g[j])&&(b.style[j]=g[j]);else void 0!==e?"href"===f?b.setAttributeNS("http://www.w3.org/1999/xlink","href",g):"className"===f?b.setAttribute("class",g):b.setAttribute(f,g):f in b?b[f]=g:b.setAttribute(f,g)}}return d}function e(a){for(var b=0;b16)b.redraw();else{var c=a.cancelAnimationFrame||a.clearTimeout,d=a.requestAnimationFrame||a.setTimeout;c(F),F=d(b.redraw,0)}}function j(a,c,d){K={};for(var e in c){if(e==d)return!void b.module(a,c[e]);var f=new RegExp("^"+e.replace(/:[^\/]+/g,"([^\\/]+)")+"$");if(f.test(d))return!void d.replace(f,function(){for(var d=e.match(/:[^\/]+/g),f=[].slice.call(arguments,1,-2),g=0;g0&&("GET"==a.method?a.url=a.url+(a.url.indexOf("?")<0?"?":"&")+o(b):a.data=c(b)),a}function q(a,b){var c=a.match(/:[a-z]\w+/gi);if(c&&b)for(var d=0;de?y.push(b)-1:e,g=b==a.document||b==a.document.documentElement?x:b;z[f]=c(g,d,z[f],!1,0)},b.trust=function(a){return a=new String(a),a.$trusted=!0,a};var A=[],B=[],C=[],D=0,E=0,F=0;b.module=function(a,c){b.startComputation();var d=A.indexOf(a);0>d&&(d=A.length),A[d]=a,B[d]=c,C[d]=new c.controller,b.endComputation()},b.redraw=function(){for(var a=0;a0&&(e.attrs[d]=h.join(" "))}e=g(e),e.attrs=g(e.attrs),e.children=b?a[2]:a[1];for(var j in c)e.attrs[j]=j==d?(e.attrs[j]||"")+" "+c[j]:c[j];return e}function c(b,g,h,i,j,k){if(null===g||void 0===g)return void(h&&e(h.nodes));if("retain"!==g.subtree){var l=u.call(h),m=u.call(g);if(l!=m&&(null!==h&&void 0!==h&&e(h.nodes),h=new g.constructor,h.nodes=[]),"[object Array]"==m){for(var n=[],o=h.length===g.length,p=0,q=0;q-1?new g.constructor(g):g,h.nodes=[s];else if(h.valueOf()!==g.valueOf()||i===!0){if(g.$trusted){var v=h.nodes[0],n=[v];if(v){for(;v=v.nextSibling;)n.push(v);e(n),s=f(b,j,g)}else b.innerHTML=g}else s=h.nodes[0],b.insertBefore(s,b.childNodes[j]||null),s.nodeValue=g;h=new g.constructor(g),h.nodes=[s]}else h.nodes.intact=!0}return h}}function d(b,c,d,e){for(var f in c){var g=c[f],i=d[f];if(!(f in d)||i!==g||b===a.document.activeElement){if(d[f]=g,"config"===f)continue;if("function"==typeof g&&0==f.indexOf("on"))b[f]=h(g,b);else if("style"===f)for(var j in g)(void 0===i||i[j]!==g[j])&&(b.style[j]=g[j]);else void 0!==e?"href"===f?b.setAttributeNS("http://www.w3.org/1999/xlink","href",g):"className"===f?b.setAttribute("class",g):b.setAttribute(f,g):f in b?b[f]=g:b.setAttribute(f,g)}}return d}function e(a){for(var b=0;b16)b.redraw();else{var c=a.cancelAnimationFrame||a.clearTimeout,d=a.requestAnimationFrame||a.setTimeout;c(F),F=d(b.redraw,0)}}function j(a,c,d){K={};for(var e in c){if(e==d)return!void b.module(a,c[e]);var f=new RegExp("^"+e.replace(/:[^\/]+/g,"([^\\/]+)")+"$");if(f.test(d))return!void d.replace(f,function(){for(var d=e.match(/:[^\/]+/g),f=[].slice.call(arguments,1,-2),g=0;g0&&("GET"==a.method?a.url=a.url+(a.url.indexOf("?")<0?"?":"&")+o(b):a.data=c(b)),a}function q(a,b){var c=a.match(/:[a-z]\w+/gi);if(c&&b)for(var d=0;de?y.push(b)-1:e,g=b==a.document||b==a.document.documentElement?x:b;z[f]=c(g,d,z[f],!1,0)},b.trust=function(a){return a=new String(a),a.$trusted=!0,a};var A=[],B=[],C=[],D=0,E=0,F=0;b.module=function(a,c){b.startComputation();var d=A.indexOf(a);0>d&&(d=A.length),A[d]=a,B[d]=c,C[d]=new c.controller,b.endComputation()},b.redraw=function(){for(var a=0;a}zV~BZzd3&0_To)j-+Z$D z+(nA~-oHaa?ex!JaEPLUZ~H!byFosxvf7qysX4n=LmzvtbhDOLDX*IqZ2{xE=!ZA$ zDInk*zp6(IjK<`dN35+{1RM8s9@Gzsd5OBd9TejBMj0&cs-@Xx#?s(~Io=ar*II&fdn{e&9blGCH|+-v^QfSR*XPF_|}GtHeWPhFIwVv5W3BX|rB!JAvE5^rVOz z@nwOuOWYB`BI#Q6%%YzQp~1CTk|%GbTq>RhladY4L~N$NqdMm@OeAG`!u3FLFEt?& zr;I1a%t?F_hy0FUaRil10=ZWj?**ep&O*;KH#_T`k}!e3W|l_o&XGjP-5F1kBzI$B zQV7cUG!DfQKZ;UWws&KOl*{OnTTTG09A27%_OsUqijse~Rit0$UzNJ1DXMGQInM4+ zDVwTAH~wupN^j|wRJIMQ(WZ3iT8++E%^U$4d<@QT0`wD0v#XX#uvT$9EBmvafx7w` zttsoXxz2}Y-`id7{d+g)=wQ^>qDHL9%kKMX8U>vmcxl4U)(oqQgLFi8S4G=rVZ$Z}_RZa#FfQ5GB`Mcryi=XmaMCZCoQt`N=u-JUZHwX&HbzN9O_1ZJ8DU5LuB{0H|;` zy|j2B(z^il9g4VG>{-2G`)q@SOx28 zO$q9S$d$@E?$TOWOwXfT5K|d~Rrs>t*P9z2qq>gT#JIRG(GuDu=FQIzibV{`%i^el zZlIuw1o(%7&0$ol30O7X#2miL*>Fa`HZ|bXgk_k}x0h~j;H#^&hUh$QQt2!TaXbiU zs44-m#wXxsotdp?@VEl&iJ(V)z@aBJVPC&GZ>ix& +
+

Extracting Metadata from the Response

+

The extract method can be used to read metadata from HTTP response headers or the status field of an XMLHttpRequest.

+
var extract = function(xhr, xhrOptions) {
+    if (xhrOptions.method == "HEAD") return xhr.getResponseHeader("x-item-count")
+    else return xhr.responseText
+}
+
+m.request({method: "POST", url: "/foo", extract: extract});
+

Configuring the underlying XMLHttpRequest

The config option can be used to arbitrarily configure the native XMLHttpRequest instance and to access properties that would not be accessible otherwise.

The example below show how to configure a request where the server expects requests to have a Content-Type: application/json header

@@ -235,14 +245,14 @@ where: [String user,] [String password,] [Object<any> data,] - [Response unwrapSuccess(Response data),] - [Response unwrapError(Response data),] + [any unwrapSuccess(any data),] + [any unwrapError(any data),] [String serialize(any dataToSerialize),] [any deserialize(String dataToDeserialize),] + [any extract(XMLHttpRequest xhr, XHROptions options),] [void type(Object<any> data),] [void config(XMLHttpRequest xhr, XHROptions options)] - } - Response :: Object<any> | Array<any> + }
  • XHROptions options

    A map of options for the XMLHttpRequest

    @@ -265,7 +275,7 @@ where:
  • Object data (optional)

    Data to be sent. It's automatically placed in the appropriate section of the request with the appropriate serialization based on method

  • -
  • Response unwrapSuccess(Response data) (optional)

    +
  • any unwrapSuccess(any data) (optional)

    A preprocessor function to extract the data from a success response in case the response contains metadata wrapping the data.

    The default value (if this parameter is falsy) is the identity function function(value) {return value}

    For example, if the response is {data: [{name: "John"}, {name: "Mary"}]} and the unwrap function is function(response) {return response.data}, then the response will be considered to be [{name: "John"}, {name: "Mary"}] when processing the type parameter

    @@ -278,7 +288,7 @@ where:
-
  • String unwrapError(Response data) (optional)

    +
  • any unwrapError(any data) (optional)

    A preprocessor function to extract the data from an error response in case the response contains metadata wrapping the data.

    The default value (if this parameter is falsy) is the identity function function(value) {return value}

      @@ -312,6 +322,10 @@ where:
  • +
  • any extract(XMLHttpRequest xhr, XHROptions options) (optional)

    +

    Method to use to extract the data from the raw XMLHttpRequest. This is useful when the relevant data is either in a response header or the status field.

    +

    If this parameter is falsy, xhr.responseText will be used.

    +
  • void type(Object data) (optional)

    The response object (or the child items if this object is an Array) will be passed as a parameter to the class constructor defined by type

    If this parameter is falsy, the deserialized data will not be wrapped.

    diff --git a/docs/mithril.request.md b/docs/mithril.request.md index 27cac116..02643d51 100644 --- a/docs/mithril.request.md +++ b/docs/mithril.request.md @@ -226,6 +226,23 @@ var file = m.request({ }); ``` +--- + +### Extracting Metadata from the Response + +The `extract` method can be used to read metadata from HTTP response headers or the status field of an XMLHttpRequest. + +```javascript +var extract = function(xhr, xhrOptions) { + if (xhrOptions.method == "HEAD") return xhr.getResponseHeader("x-item-count") + else return xhr.responseText +} + +m.request({method: "POST", url: "/foo", extract: extract}); +``` + +--- + ### Configuring the underlying XMLHttpRequest The `config` option can be used to arbitrarily configure the native XMLHttpRequest instance and to access properties that would not be accessible otherwise. @@ -258,14 +275,14 @@ where: [String user,] [String password,] [Object data,] - [Response unwrapSuccess(Response data),] - [Response unwrapError(Response data),] + [any unwrapSuccess(any data),] + [any unwrapError(any data),] [String serialize(any dataToSerialize),] [any deserialize(String dataToDeserialize),] + [any extract(XMLHttpRequest xhr, XHROptions options),] [void type(Object data),] [void config(XMLHttpRequest xhr, XHROptions options)] } - Response :: Object | Array ``` - **XHROptions options** @@ -296,7 +313,7 @@ where: Data to be sent. It's automatically placed in the appropriate section of the request with the appropriate serialization based on `method` - - **Response unwrapSuccess(Response data)** (optional) + - **any unwrapSuccess(any data)** (optional) A preprocessor function to extract the data from a success response in case the response contains metadata wrapping the data. @@ -312,7 +329,7 @@ where: The unwrapped data - - **String unwrapError(Response data)** (optional) + - **any unwrapError(any data)** (optional) A preprocessor function to extract the data from an error response in case the response contains metadata wrapping the data. @@ -349,7 +366,13 @@ where: Data to be deserialized - **returns any deserializedData** + + - **any extract(XMLHttpRequest xhr, XHROptions options)** (optional) + + Method to use to extract the data from the raw XMLHttpRequest. This is useful when the relevant data is either in a response header or the status field. + If this parameter is falsy, `xhr.responseText` will be used. + - **void type(Object data)** (optional) The response object (or the child items if this object is an Array) will be passed as a parameter to the class constructor defined by `type` diff --git a/mithril.js b/mithril.js index 91aa2e83..d9b1cce7 100644 --- a/mithril.js +++ b/mithril.js @@ -430,11 +430,12 @@ Mithril = m = new function app(window) { var deferred = m.deferred() var serialize = xhrOptions.serialize || JSON.stringify var deserialize = xhrOptions.deserialize || JSON.parse + var extract = xhrOptions.extract || function(xhr, xhrOptions) {return xhr.responseText} xhrOptions.url = parameterizeUrl(xhrOptions.url, xhrOptions.data) xhrOptions = bindData(xhrOptions, xhrOptions.data, serialize) xhrOptions.onload = xhrOptions.onerror = function(e) { var unwrap = (e.type == "load" ? xhrOptions.unwrapSuccess : xhrOptions.unwrapError) || identity - var response = unwrap(deserialize(e.target.responseText)) + var response = unwrap(deserialize(extract(e.target, xhrOptions))) if (response instanceof Array && xhrOptions.type) { for (var i = 0; i < response.length; i++) response[i] = new xhrOptions.type(response[i]) }