github.com/enmand/kubernetes@v1.2.0-alpha.0/third_party/swagger-ui/lib/shred/content.js (about) 1 2 // The purpose of the `Content` object is to abstract away the data conversions 3 // to and from raw content entities as strings. For example, you want to be able 4 // to pass in a Javascript object and have it be automatically converted into a 5 // JSON string if the `content-type` is set to a JSON-based media type. 6 // Conversely, you want to be able to transparently get back a Javascript object 7 // in the response if the `content-type` is a JSON-based media-type. 8 9 // One limitation of the current implementation is that it [assumes the `charset` is UTF-8](https://github.com/spire-io/shred/issues/5). 10 11 // The `Content` constructor takes an options object, which *must* have either a 12 // `body` or `data` property and *may* have a `type` property indicating the 13 // media type. If there is no `type` attribute, a default will be inferred. 14 var Content = function(options) { 15 this.body = options.body; 16 this.data = options.data; 17 this.type = options.type; 18 }; 19 20 Content.prototype = { 21 // Treat `toString()` as asking for the `content.body`. That is, the raw content entity. 22 // 23 // toString: function() { return this.body; } 24 // 25 // Commented out, but I've forgotten why. :/ 26 }; 27 28 29 // `Content` objects have the following attributes: 30 Object.defineProperties(Content.prototype,{ 31 32 // - **type**. Typically accessed as `content.type`, reflects the `content-type` 33 // header associated with the request or response. If not passed as an options 34 // to the constructor or set explicitly, it will infer the type the `data` 35 // attribute, if possible, and, failing that, will default to `text/plain`. 36 type: { 37 get: function() { 38 if (this._type) { 39 return this._type; 40 } else { 41 if (this._data) { 42 switch(typeof this._data) { 43 case "string": return "text/plain"; 44 case "object": return "application/json"; 45 } 46 } 47 } 48 return "text/plain"; 49 }, 50 set: function(value) { 51 this._type = value; 52 return this; 53 }, 54 enumerable: true 55 }, 56 57 // - **data**. Typically accessed as `content.data`, reflects the content entity 58 // converted into Javascript data. This can be a string, if the `type` is, say, 59 // `text/plain`, but can also be a Javascript object. The conversion applied is 60 // based on the `processor` attribute. The `data` attribute can also be set 61 // directly, in which case the conversion will be done the other way, to infer 62 // the `body` attribute. 63 data: { 64 get: function() { 65 if (this._body) { 66 return this.processor.parser(this._body); 67 } else { 68 return this._data; 69 } 70 }, 71 set: function(data) { 72 if (this._body&&data) Errors.setDataWithBody(this); 73 this._data = data; 74 return this; 75 }, 76 enumerable: true 77 }, 78 79 // - **body**. Typically accessed as `content.body`, reflects the content entity 80 // as a UTF-8 string. It is the mirror of the `data` attribute. If you set the 81 // `data` attribute, the `body` attribute will be inferred and vice-versa. If 82 // you attempt to set both, an exception is raised. 83 body: { 84 get: function() { 85 if (this._data) { 86 return this.processor.stringify(this._data); 87 } else { 88 return this._body.toString(); 89 } 90 }, 91 set: function(body) { 92 if (this._data&&body) Errors.setBodyWithData(this); 93 this._body = body; 94 return this; 95 }, 96 enumerable: true 97 }, 98 99 // - **processor**. The functions that will be used to convert to/from `data` and 100 // `body` attributes. You can add processors. The two that are built-in are for 101 // `text/plain`, which is basically an identity transformation and 102 // `application/json` and other JSON-based media types (including custom media 103 // types with `+json`). You can add your own processors. See below. 104 processor: { 105 get: function() { 106 var processor = Content.processors[this.type]; 107 if (processor) { 108 return processor; 109 } else { 110 // Return the first processor that matches any part of the 111 // content type. ex: application/vnd.foobar.baz+json will match json. 112 var main = this.type.split(";")[0]; 113 var parts = main.split(/\+|\//); 114 for (var i=0, l=parts.length; i < l; i++) { 115 processor = Content.processors[parts[i]] 116 } 117 return processor || {parser:identity,stringify:toString}; 118 } 119 }, 120 enumerable: true 121 }, 122 123 // - **length**. Typically accessed as `content.length`, returns the length in 124 // bytes of the raw content entity. 125 length: { 126 get: function() { 127 if (typeof Buffer !== 'undefined') { 128 return Buffer.byteLength(this.body); 129 } 130 return this.body.length; 131 } 132 } 133 }); 134 135 Content.processors = {}; 136 137 // The `registerProcessor` function allows you to add your own processors to 138 // convert content entities. Each processor consists of a Javascript object with 139 // two properties: 140 // - **parser**. The function used to parse a raw content entity and convert it 141 // into a Javascript data type. 142 // - **stringify**. The function used to convert a Javascript data type into a 143 // raw content entity. 144 Content.registerProcessor = function(types,processor) { 145 146 // You can pass an array of types that will trigger this processor, or just one. 147 // We determine the array via duck-typing here. 148 if (types.forEach) { 149 types.forEach(function(type) { 150 Content.processors[type] = processor; 151 }); 152 } else { 153 // If you didn't pass an array, we just use what you pass in. 154 Content.processors[types] = processor; 155 } 156 }; 157 158 // Register the identity processor, which is used for text-based media types. 159 var identity = function(x) { return x; } 160 , toString = function(x) { return x.toString(); } 161 Content.registerProcessor( 162 ["text/html","text/plain","text"], 163 { parser: identity, stringify: toString }); 164 165 // Register the JSON processor, which is used for JSON-based media types. 166 Content.registerProcessor( 167 ["application/json; charset=utf-8","application/json","json"], 168 { 169 parser: function(string) { 170 return JSON.parse(string); 171 }, 172 stringify: function(data) { 173 return JSON.stringify(data); }}); 174 175 var qs = require('querystring'); 176 // Register the post processor, which is used for JSON-based media types. 177 Content.registerProcessor( 178 ["application/x-www-form-urlencoded"], 179 { parser : qs.parse, stringify : qs.stringify }); 180 181 // Error functions are defined separately here in an attempt to make the code 182 // easier to read. 183 var Errors = { 184 setDataWithBody: function(object) { 185 throw new Error("Attempt to set data attribute of a content object " + 186 "when the body attributes was already set."); 187 }, 188 setBodyWithData: function(object) { 189 throw new Error("Attempt to set body attribute of a content object " + 190 "when the data attributes was already set."); 191 } 192 } 193 module.exports = Content;