diff --git a/README.md b/README.md index 913fdfe3..b6e99098 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,6 @@ There are over 4000 assertions in the test suite, and tests cover even difficult ## Modularity -Despite the huge improvements in performance and modularity, the new codebase is smaller than v0.2.x, currently clocking at 7.55 KB min+gzip +Despite the huge improvements in performance and modularity, the new codebase is smaller than v0.2.x, currently clocking at 7.59 KB min+gzip In addition, Mithril is now completely modular: you can import only the modules that you need and easily integrate 3rd party modules if you wish to use a different library for routing, ajax, and even rendering diff --git a/docs/request.md b/docs/request.md index 75be0de9..3671f957 100644 --- a/docs/request.md +++ b/docs/request.md @@ -50,6 +50,7 @@ Argument | Type | Required | Descr `options.password` | `String` | No | A password for HTTP authorization. Defaults to `undefined`. This option is provided for `XMLHttpRequest` compatibility, but you should avoid using it because it sends the password in plain text over the network. `options.withCredentials` | `Boolean` | No | Whether to send cookies to 3rd party domains. Defaults to `false` `options.config` | `xhr = Function(xhr)` | No | Exposes the underlying XMLHttpRequest object for low-level configuration. Defaults to the [identity function](https://en.wikipedia.org/wiki/Identity_function). +`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 `data`. Defaults to `JSON.stringify`, or if `options.data` 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.deserialize` | `any = Function(string)` | No | A deserialization method to be applied to the response. Defaults to a small wrapper around `JSON.parse` that returns `null` for empty responses. @@ -404,7 +405,21 @@ function parseCSV(data) { } ``` -Ignoring the fact that the parseCSV function above doesn't handle a lot of cases that a proper CSV parser would, the code above logs an array of arrays +Ignoring the fact that the parseCSV function above doesn't handle a lot of cases that a proper CSV parser would, the code above logs an array of arrays. + +Custom headers may also be helpful in this regard. For example, if you're requesting an SVG, you probably want to set the content type accordingly. To override the default JSON request type, set `options.headers` to an object of key-value pairs corresponding to request header names and values. + +```javascript +m.request({ + method: "GET", + url: "/files/image.svg", + headers: { + "Content-Type": "image/svg+xml; charset=utf-8", + "Accept": "image/svg, text/*" + }, + deserialize: function(value) {return value} +}) +``` --- @@ -485,4 +500,3 @@ m.request("/api/v1/users").then(function(users) { console.log("list of users:", users) }) ``` - diff --git a/mithril.js b/mithril.js index 074077db..55810181 100644 --- a/mithril.js +++ b/mithril.js @@ -232,7 +232,6 @@ var _8 = function($window, Promise) { } return args } - function request(args, extra) { var finalize = finalizer() args = normalize(args, extra) @@ -255,6 +254,9 @@ var _8 = function($window, Promise) { xhr.setRequestHeader("Accept", "application/json, text/*") } if (args.withCredentials) xhr.withCredentials = args.withCredentials + for (var key in args.headers) if ({}.hasOwnProperty.call(args.headers, key)) { + xhr.setRequestHeader(key, args.headers[key]) + } if (typeof args.config === "function") xhr = args.config(xhr, args) || xhr xhr.onreadystatechange = function() { if (xhr.readyState === 4) { @@ -282,7 +284,6 @@ var _8 = function($window, Promise) { function jsonp(args, extra) { var finalize = finalizer() args = normalize(args, extra) - var promise0 = new Promise(function(resolve, reject) { var callbackName = args.callbackName || "_mithril_" + Math.round(Math.random() * 1e16) + "_" + callbackCount++ var script = $window.document.createElement("script") diff --git a/mithril.min.js b/mithril.min.js index fe499750..ddf9415f 100644 --- a/mithril.min.js +++ b/mithril.min.js @@ -1,42 +1,42 @@ -new function(){function w(a,c,g,d,f,l){return{tag:a,key:c,attrs:g,children:d,text:f,dom:l,domSize:void 0,state:{},events:void 0,instance:void 0,skip:!1}}function A(a){if(null==a||"string"!==typeof a&&null==a.view)throw Error("The selector must be either a string or a component.");if("string"===typeof a&&void 0===G[a]){for(var c,g,d=[],f={};c=N.exec(a);){var l=c[1],k=c[2];""===l&&""!==k?g=k:"#"===l?f.id=k:"."===l?d.push(k):"["===c[3][0]&&((l=c[6])&&(l=l.replace(/\\(["'])/g,"$1").replace(/\\\\/g,"\\")), -"class"===c[4]?d.push(l):f[c[4]]=l||!0)}0a.indexOf("?")?"?":"&";a+=d+b}return a}function k(a){try{return""!==a?JSON.parse(a):null}catch(C){throw Error(a); -}}function r(a){return a.responseText}function q(a,c){if("function"===typeof a)if(c instanceof Array)for(var b=0;bm.status||304===m.status)c(q(b.type,a));else{var f=Error(m.responseText),g;for(g in a)f[g]=a[g];d(f)}}catch(e){d(e)}};g&&null!=b.data?m.send(b.data):m.send()});return!0===b.background?z:u(z)}, -jsonp:function(b,k){var r=g();b=d(b,k);var u=new c(function(c,d){var g=b.callbackName||"_mithril_"+Math.round(1E16*Math.random())+"_"+m++,k=a.document.createElement("script");a[g]=function(d){k.parentNode.removeChild(k);c(q(b.type,d));delete a[g]};k.onerror=function(){k.parentNode.removeChild(k);d(Error("JSONP request failed"));delete a[g]};null==b.data&&(b.data={});b.url=f(b.url,b.data);b.data[b.callbackKey||"callback"]=g;k.src=l(b.url,b.data);a.document.documentElement.appendChild(k)});return!0=== -b.background?u:r(u)},setCompletionCallback:function(a){u=a}}}(window,x),M=function(a){function c(e,h,a,b,c,d,f){for(;a=t&&z>=u;){var y=a[t],n=p[u];if(y!==n||h)if(null==y)t++;else if(null==n)u++;else if(y.key===n.key)t++,u++,k(e,y,n,d,q(a,t,f),h,l),h&&y.tag===n.tag&&m(e,r(y),f);else if(y=a[v],y!==n||h)if(null==y)v--;else if(null==n)u++;else if(y.key===n.key)k(e, -y,n,d,q(a,v+1,f),h,l),(h||u=t&&z>=u;){y=a[v];n=p[z];if(y!==n||h)if(null==y)v--;else{if(null!=n)if(y.key===n.key)k(e,y,n,d,q(a,v+1,f),h,l),h&&y.tag===n.tag&&m(e,r(y),f),null!=y.dom&&(f=y.dom),v--;else{if(!C){C=a;var y=v,E={},w;for(w=0;wa.indexOf("?")?"?":"&";a+=d+c}return a}function m(b){try{return""!==b?JSON.parse(b):null}catch(C){throw Error(b); +}}function q(b){return b.responseText}function n(b,c){if("function"===typeof b)if(c instanceof Array)for(var a=0;ak.status||304===k.status)c(n(a.type,b));else{var g=Error(k.responseText),e;for(e in b)g[e]=b[e]; +d(g)}}catch(f){d(f)}};h&&null!=a.data?k.send(a.data):k.send()});return!0===a.background?z:t(z)},jsonp:function(a,m){var t=h();a=d(a,m);var q=new c(function(c,d){var h=a.callbackName||"_mithril_"+Math.round(1E16*Math.random())+"_"+k++,m=b.document.createElement("script");b[h]=function(d){m.parentNode.removeChild(m);c(n(a.type,d));delete b[h]};m.onerror=function(){m.parentNode.removeChild(m);d(Error("JSONP request failed"));delete b[h]};null==a.data&&(a.data={});a.url=g(a.url,a.data);a.data[a.callbackKey|| +"callback"]=h;m.src=l(a.url,a.data);b.document.documentElement.appendChild(m)});return!0===a.background?q:t(q)},setCompletionCallback:function(b){t=b}}}(window,x),M=function(b){function c(e,f,b,a,c,d,g){for(;b=u&&z>=t;){var y=f[u],p=b[t];if(y!==p||r)if(null==y)u++;else if(null==p)t++;else if(y.key===p.key)u++,t++,m(e,y,p,d,n(f,u,g),r,l),r&&y.tag=== +p.tag&&k(e,q(y),g);else if(y=f[v],y!==p||r)if(null==y)v--;else if(null==p)t++;else if(y.key===p.key)m(e,y,p,d,n(f,v+1,g),r,l),(r||t=u&&z>=t;){y=f[v];p=b[z];if(y!==p||r)if(null==y)v--;else{if(null!=p)if(y.key===p.key)m(e,y,p,d,n(f,v+1,g),r,l),r&&y.tag===p.tag&&k(e,q(y),g),null!=y.dom&&(g=y.dom),v--;else{if(!C){C=f;var y=v,E={},w;for(w=0;w