Guest User

Untitled

a guest
Dec 12th, 2018
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.69 KB | None | 0 0
  1. import fetch from 'node-fetch';
  2.  
  3. let content_type = "application/vnd.collection+json";
  4.  
  5. class HttpImplementation {
  6.  
  7. // http_callback is used by each of the verb-methods below.
  8. // It should call `done` with (error_string_or_null, body_as_text,
  9. // response_headers)
  10. //
  11. http_callback(response, done) {
  12. if(response.status < 400) {
  13. // strangely, response.text() returns a promise...
  14. response.text().then((actual_response) => {
  15. done(null, actual_response, response.headers)
  16. })
  17. }
  18. else { done(response.status); }
  19. }
  20.  
  21. get(href, options, done) {
  22. fetch(href).then((response) => {this.http_callback(response, done)}).
  23. catch(error => done(error));
  24. };
  25.  
  26. post(href, options, done) {
  27. http_options = Object.assign({}, options,
  28. {
  29. method: "POST", body: JSON.stringify(options.body),
  30. headers: options.headers,
  31. redirect: "follow", mode: "CORS",
  32. credentials: "same-origin", referrer: "client",
  33. })
  34.  
  35. return(fetch(href, http_options).then(this.http_callback, done));
  36. };
  37.  
  38. put(href, options, done) {
  39. http_options = Object.assign({}, options,
  40. {
  41. method: "PUT", body: JSON.stringify(options.body),
  42. headers: headers,
  43. redirect: "follow", mode: "CORS",
  44. credentials: "same-origin", referrer: "client",
  45. })
  46.  
  47. return(fetch(href, http_options).then(this.http_callback, done));
  48. }
  49.  
  50. delete(href, options, done){
  51. http_options = Object.assign({}, options,
  52. {
  53. method: "DELETE", body: JSON.stringify(options.body),
  54. headers: headers,
  55. redirect: "follow", mode: "CORS",
  56. credentials: "same-origin", referrer: "client",
  57. })
  58.  
  59. return(fetch(href, http_options).then(http_callback, done));
  60. };
  61. }
  62.  
  63. class InterfaceLayer {
  64. constructor( network_layer )
  65. {
  66. if( network_layer == null || network_layer == undefined )
  67. { this.source = new HttpImplementation(); }
  68. else
  69. { this.source = network_layer ; }
  70. }
  71.  
  72. get(href, options, done) {
  73. if(!options.headers) { options.headers = {} }
  74. options.headers["accept"] = content_type;
  75.  
  76. this.source.get(href, options, function(error, collection, headers) {
  77. // the previous implementation of this was async, so
  78. // it might bear reworking once figured out
  79. // seems like you could add a layer that would try each one
  80. // and, on failure, try the next.
  81.  
  82. if( error || collection )
  83. {
  84. // if a collection is returned, the source should handle caching
  85. // though in the original code...
  86. // https://github.com/collection-json/collection-json.js/blob/master/lib/http.coffee#L49
  87. return(done(error, collection, headers));
  88. }
  89. else
  90. {
  91. return(false);
  92. }
  93. })
  94. }
  95.  
  96. post(href, options, done) {
  97. if (options == null) { options = {}; }
  98. if (!options.headers) { options.headers = {}; }
  99.  
  100. options.headers = Object.assign({}, options.headers, {
  101. "accept": content_type,
  102. "content-type": content_type,
  103. "Content-Type": "application/collection+json; charset=utf-8"
  104. })
  105.  
  106. this.source.post(href, options, function(error, collection, headers)
  107. {
  108. if( error || collection )
  109. {
  110. // if a collection is returned, the source should handle caching
  111. // though in the original code...
  112. // https://github.com/collection-json/collection-json.js/blob/master/lib/http.coffee#L49
  113. return(done(error, collection, headers));
  114. }
  115. else
  116. {
  117. return(false);
  118. }
  119. })
  120. }
  121.  
  122. put(href, options, done) {
  123. if (options == null) { options = {}; }
  124. if (!options.headers) { options.headers = {}; }
  125.  
  126. options.headers = Object.assign({}, options.headers, {
  127. "accept": content_type,
  128. "content-type": content_type,
  129. "Content-Type": "application/collection+json; charset=utf-8"
  130. })
  131.  
  132. this.source.put(href, options, function(error, collection, headers)
  133. {
  134. if( error || collection )
  135. {
  136. // if a collection is returned, the source should handle caching
  137. // though in the original code...
  138. // https://github.com/collection-json/collection-json.js/blob/master/lib/http.coffee#L49
  139. return(done(error, collection, headers));
  140. }
  141. else
  142. {
  143. return(false);
  144. }
  145. })
  146. }
  147.  
  148. delete(href, options, done) {
  149. if (options == null) { options = {}; }
  150. if (!options.headers) { options.headers = {}; }
  151.  
  152. options.headers = Object.assign({}, options.headers, {
  153. "accept": content_type,
  154. "content-type": content_type,
  155. "Content-Type": "application/collection+json; charset=utf-8"
  156. })
  157.  
  158. this.source.delete(href, options, function(error, collection, headers)
  159. {
  160. if( error || collection )
  161. {
  162. // if a collection is returned, the source should handle caching
  163. // though in the original code...
  164. // https://github.com/collection-json/collection-json.js/blob/master/lib/http.coffee#L49
  165. return(done(error, collection, headers));
  166. }
  167. else
  168. {
  169. return(false);
  170. }
  171. })
  172. }
  173. }
  174.  
  175. export default (new InterfaceLayer())
  176.  
  177. import Client from '../src/client.js'
  178.  
  179. describe("LIVE test from ACTUAL API", () => {
  180. test("it gets an error when calling an invalid path", () => {
  181. new Client('http://todo-collection-json.herokuapp.com/invalid',
  182. (error, collection) => {
  183. expect(error).toBe(404);
  184. expect(collection).toBeUndefined();
  185. });
  186. })
  187.  
  188. test('it works with a real-life-ish example', () => {
  189. expect.assertions();
  190.  
  191. new Client('http://todo-collection-json.herokuapp.com/collection/tasks/',
  192. (error, collection) => {
  193. expect(collection).not.toBeDefined();
  194. console.log(collection);
  195. expect(error).toBeNull();
  196. });
  197. })
  198. })
  199.  
  200. module.exports = defaults =
  201. _get: (href, options, done=()->)->
  202. done new Error "'GET' not implemented"
  203.  
  204. _post: (href, options, done=()->)->
  205. done new Error "'POST' not implemented"
  206.  
  207. _put: (href, options, done=()->)->
  208. done new Error "'PUT' not implemented"
  209.  
  210. _del: (href, options, done=()->)->
  211. done new Error "'DELETE' not implemented"
  212.  
  213. cache:
  214. # This is a fake cache. You should probably add a real one...
  215. put: (key, value, time, done=()->)->
  216. if typeof time is 'function'
  217. done = time
  218. time = null
  219. done()
  220. del: (key, done=()->)->
  221. done()
  222. clear: (done=()->)->
  223. done()
  224. get: (key, done=()->)->
  225. done()
  226. size: (done=()->)->
  227. done 0
  228. memsize: (done=()->)->
  229. done 0
  230. debug: ()->
  231. true
  232.  
  233. module.exports["content-type"] = "application/vnd.collection+json"
  234.  
  235. module.exports.get = (href, options, done)->
  236. defaults.cache.get href, (error, collection)->
  237. # Give them the cached stuff if we have it
  238. return done error, collection if error or collection
  239.  
  240. options.headers ||= {}
  241. options.headers["accept"] = module.exports["content-type"]
  242.  
  243. module.exports.setOptions href, options
  244.  
  245. defaults._get href, options, (error, collection, headers)->
  246. return done error if error
  247. performCache collection, headers
  248. done error, collection
  249.  
  250. module.exports.post = (href, options={}, done)->
  251.  
  252. options.headers ||= {}
  253. options.headers["accept"] = module.exports["content-type"]
  254. options.headers["content-type"] = module.exports["content-type"]
  255.  
  256. module.exports.setOptions href, options
  257.  
  258. defaults._post href, options, (error, collection, headers)->
  259. # Do we cache this?
  260. done error, collection
  261.  
  262. # Should be overridden by the client
  263. module.exports.setOptions = (href, options)->
  264.  
  265. performCache = (collection, headers)->
  266. # Expires
  267. # expires = response.headers.expires
  268. # # TODO convert to time-from-now
  269. # # Cache-Control
  270. # # TODO implement
  271. # defaults.cache.put response.request.href, response.body, new Date(expires).getTime() if expires
  272.  
  273.  
  274. //=====================================================================
  275. // in another file, lib/index.coffee...
  276. //=====================================================================
  277.  
  278. request = require "request"
  279. http = require "./http"
  280.  
  281. http._get = (href, options, done)->
  282. options.url = href
  283. request options, (error, response, body)->
  284. done error, body, response?.headers
  285.  
  286. http._post = (href, options, done)->
  287. options.url = href
  288. options.body = JSON.stringify options.body
  289. options.method = "POST"
  290. request options, (error, response, body)->
  291. done error, body, response?.headers
  292.  
  293. http._put = (href, options, done)->
  294. options.url = href
  295. options.body = JSON.stringify options.body
  296. request.put options, (error, response)->
  297. done error, response
  298.  
  299. http._del = (href, options, done)->
  300. options.url = href
  301. request.del options, (error, response)->
  302. done error, response
  303.  
  304. module.exports = require "./client"
Add Comment
Please, Sign In to add comment