1- var request = require ( 'request' ) ;
1+ // var request = require('request');
22var http = require ( 'http' ) ;
33var prettyjson = require ( 'prettyjson' ) ;
44var fs = require ( 'fs' ) ;
5+ var stream = require ( 'stream' ) ;
6+ var util = require ( 'util' ) ;
7+
8+ const streamPipeline = util . promisify ( stream . pipeline ) ;
59
610var mem = { history : [ ] } ;
711
@@ -15,7 +19,7 @@ async function handleClientError(self, response) {
1519 const text = await response . text ( ) ;
1620 var info = {
1721 status : self . status ,
18- error : text
22+ message : text
1923 } ;
2024 neat ( { response : info } ) ;
2125}
@@ -40,9 +44,16 @@ async function handle200OK(self, url, requestOptions, response) {
4044 const text = await response . text ( ) ;
4145 const contentType = response . headers . get ( 'content-type' ) ;
4246 handlePlace ( self , url , text , contentType ) ;
47+
48+ const etag = response . headers . get ( 'etag' ) ;
49+ mem [ url ] = {
50+ etag : etag ,
51+ text : text
52+ } ;
53+
4354 var info = {
4455 status : self . status ,
45- etag : response . headers . get ( ' etag' ) ,
56+ etag : etag ,
4657 'content-type' : contentType
4758 } ;
4859
@@ -145,7 +156,6 @@ async function handle418ImATeapot(self, response) {
145156}
146157
147158async function sendRequest ( self , url , requestOptions ) {
148-
149159 try {
150160 const response = await fetch ( url , requestOptions ) ;
151161
@@ -188,28 +198,58 @@ async function sendRequest(self, url, requestOptions) {
188198 case 404 :
189199 await handleClientError ( self , response ) ;
190200 break ;
201+ case 405 :
202+ await handleClientError ( self , response ) ;
203+ break ;
204+ case 406 :
205+ await handleClientError ( self , response ) ;
206+ break ;
191207 case 410 :
192208 await handleClientError ( self , response ) ;
193209 break ;
194210 case 418 :
195211 await handle418ImATeapot ( self , response ) ;
196212 break ;
197213 default :
198- console . log ( "NO HANDLER FOR " + response . status ) ;
199- console . log ( "???????????????" ) ;
200- console . log ( response ) ;
214+ console . log ( "No handler defined for " + response . status ) ;
201215 break ;
202216 }
203217 }
204218 catch ( error ) {
205219 console . error ( 'Error fetching data:' , error ) ;
206220 }
221+ }
207222
223+ async function downloadFile ( url , fileName ) {
224+ try {
225+ const response = await fetch ( url ) ;
226+ if ( response . ok ) {
227+ const destPath = `downloads/${ fileName } ` ;
228+ await streamPipeline ( response . body , fs . createWriteStream ( destPath ) ) ;
229+ var info = {
230+ 'content-type' : response . headers . get ( 'content-type' ) ,
231+ path : destPath ,
232+ bytes : response . headers . get ( 'content-length' )
233+ }
234+ neat ( info ) ;
235+ }
236+ else {
237+ var statusName = http . STATUS_CODES [ response . statusCode ] ;
238+ var statusText = resp . statusCode + " " + statusName ;
239+ // Maybe just response.statusText?
240+ neat ( { error : statusText } ) ;
241+ }
242+ } catch ( error ) {
243+ console . error ( 'Error downloading file:' , error ) ;
244+ }
208245}
209246
210- var visit = function ( self , url , requestOptions = { method : 'GET' , headers : { } , redirect : 'manual' } ) {
211- console . log ( `visit ${ url } ` ) ;
212- console . log ( requestOptions ) ;
247+ var visit = function ( self , url , requestOptions ) {
248+ requestOptions = requestOptions || { } ;
249+ requestOptions . method = requestOptions . method || 'GET' ;
250+ requestOptions . headers = requestOptions . headers || { } ;
251+ requestOptions . headers [ 'accept' ] = requestOptions . headers [ 'accept' ] || 'application/vnd.siren+json' ;
252+ requestOptions . redirect = 'manual'
213253
214254 if ( self . at ) {
215255 requestOptions . headers [ 'referer' ] = self . at ;
@@ -222,6 +262,12 @@ var visit = function(self, url, requestOptions = { method: 'GET', headers: {}, r
222262 accept : requestOptions . headers [ 'accept' ] || 'application/vnd.siren+json' ,
223263 }
224264
265+ if ( requestOptions . method === 'GET' && mem [ url ] ) {
266+ const etag = mem [ url ] . etag ;
267+ requestOptions . headers [ "If-None-Match" ] = etag ;
268+ info [ "if-none-match" ] = etag ;
269+ }
270+
225271 // Cumbersome recreation of original body from URLSearchParams.
226272 if ( requestOptions . body ) {
227273 var body = { }
@@ -279,37 +325,9 @@ var neat = function(json) {
279325 }
280326} ;
281327
282- var down = function ( uri , filename ) {
283- request . head ( uri , function ( err , res , body ) {
284-
285- if ( err ) {
286- neat ( { error : err } ) ;
287- return ;
288- }
289-
290- var r = request ( uri ) ;
291- r . on ( 'response' , function ( resp ) {
292- if ( resp . statusCode === 200 ) {
293- r . pipe ( fs . createWriteStream ( "downloads/" + filename ) ) ;
294- var resInfo = {
295- "content-type" : res . headers [ 'content-type' ] ,
296- downloaded : filename ,
297- bytes : res . headers [ 'content-length' ]
298- } ;
299- neat ( resInfo ) ;
300- }
301- else {
302- var statusName = http . STATUS_CODES [ resp . statusCode ] ;
303- var statusText = resp . statusCode + " " + statusName ;
304- neat ( { error : statusText } ) ;
305- }
306- } ) ;
307- } ) ;
308- } ;
309-
310- exports . download = function ( uri , filename ) {
311- filename = filename || uri . substring ( uri . lastIndexOf ( '/' ) + 1 )
312- down ( uri , filename , function ( ) { console . log ( "done..." ) ; } ) ;
328+ exports . download = function ( url , filename ) {
329+ filename = filename || url . substring ( url . lastIndexOf ( '/' ) + 1 ) ;
330+ downloadFile ( url , filename ) ;
313331} ;
314332
315333exports . to = function ( url , accepts ) {
@@ -489,11 +507,10 @@ exports.back = function() {
489507exports . follow = function ( ) {
490508 var self = this ;
491509 if ( self . destination ) {
492- console . log ( "Following location header to destination " + self . destination ) ;
493510 visit ( self , self . destination ) ;
494511 }
495512 else {
496- console . log ( 'No destination set through location header .' ) ;
513+ console . log ( 'No destination set.' ) ;
497514 }
498515} ;
499516
0 commit comments