@@ -41,34 +41,40 @@ function TimegateController(options) {
41
41
}
42
42
Controller . extend ( TimegateController ) ;
43
43
44
- // Tries to serve the requested Timegate
44
+ // Perform time negotiation if applicable
45
45
TimegateController . prototype . _handleRequest = function ( request , response , next ) {
46
- var self = this , timegateMatch = this . _matcher && this . _matcher . exec ( request . url ) ,
47
- datasource = timegateMatch && timegateMatch [ 1 ] ;
48
- if ( datasource && this . _timemaps [ datasource ] ) {
49
- // retrieve Accept-Datetime & construct memento link
50
- var acceptDatetime = toDate ( request . headers [ 'accept-datetime' ] ) , // If no datetime is present, return most recent one
51
- memento = this . _getClosestMemento ( this . _timemaps [ datasource ] . timemap , acceptDatetime ) ;
52
-
53
- // memento invalid, go to next
54
- if ( ! memento ) next ( ) ;
55
-
56
- // Construct memento and Original url
57
- var mementoUrl = url . format ( _ . assign ( request . parsedUrl , { pathname : memento . dataSource } ) ) ,
58
- parsedOriginalUrl = this . _timemaps [ datasource ] . originalBaseURL ? // If originalBaseURL is present, the original is external
59
- _ . assign ( url . parse ( this . _timemaps [ datasource ] . originalBaseURL ) , { query : request . parsedUrl . query } ) :
60
- _ . defaults ( { pathname : datasource } , request . parsedUrl ) ,
61
- originalUrl = url . format ( parsedOriginalUrl ) ;
62
-
63
- response . writeHead ( 303 , {
64
- 'Location' : mementoUrl ,
65
- 'Vary' : 'Accept, Accept-Datetime' ,
66
- 'Link' : '<' + originalUrl + '>;rel="original", <' + mementoUrl + '>;rel="memento";datetime="' + memento . interval [ 0 ] . toUTCString ( ) + '"'
67
- } ) ;
68
- response . end ( ) ;
46
+ var self = this , timegateMatch = this . _matcher . exec ( request . url ) ,
47
+ datasource = timegateMatch && timegateMatch [ 1 ] ,
48
+ timemapDetails = datasource && this . _timemaps [ datasource ] ;
49
+ if ( timemapDetails ) {
50
+ // Try to find the memento closest to the requested date
51
+ var acceptDatetime = toDate ( request . headers [ 'accept-datetime' ] ) ,
52
+ memento = this . _getClosestMemento ( timemapDetails . timemap , acceptDatetime ) ;
53
+ if ( memento ) {
54
+ // Determine the URL of the memento
55
+ var mementoUrl = _ . assign ( request . parsedUrl , { pathname : memento . dataSource } ) ;
56
+ mementoUrl = url . format ( mementoUrl ) ;
57
+
58
+ // Determine the URL of the original resource
59
+ var originalBaseURL = timemapDetails . originalBaseURL , originalUrl ;
60
+ if ( ! originalBaseURL )
61
+ originalUrl = _ . defaults ( { pathname : datasource } , request . parsedUrl ) ;
62
+ else
63
+ originalUrl = _ . assign ( url . parse ( originalBaseURL ) , { query : request . parsedUrl . query } ) ;
64
+ originalUrl = url . format ( originalUrl ) ;
65
+
66
+ // Perform 200-style negotiation (https://tools.ietf.org/html/rfc7089#section-4.1.2)
67
+ response . setHeader ( 'Link' , '<' + originalUrl + '>;rel="original",' +
68
+ '<' + mementoUrl + '>;rel="memento";' +
69
+ 'datetime="' + memento . interval [ 0 ] . toUTCString ( ) + '"' ) ;
70
+ response . setHeader ( 'Vary' , 'Accept-Datetime' ) ;
71
+ response . setHeader ( 'Content-Location' , mementoUrl ) ;
72
+ // Set request URL to the memento URL, which should be handled by a next controller
73
+ request . url = mementoUrl . replace ( / ^ [ ^ : ] + : \/ \/ [ ^ \/ ] + / , '' ) ;
74
+ delete request . parsedUrl ;
75
+ }
69
76
}
70
- else
71
- next ( ) ;
77
+ next ( ) ;
72
78
} ;
73
79
74
80
/*
0 commit comments