@@ -4,6 +4,9 @@ var http = require('http')
4
4
var https = require ( 'https' )
5
5
var url = require ( 'url' )
6
6
var xtend = require ( 'xtend' )
7
+ var concat = require ( 'concat-stream' )
8
+ var pump = require ( 'pump' )
9
+ var limitStream = require ( 'size-limit-stream' )
7
10
8
11
module . exports = RandomAccessHTTP
9
12
@@ -35,16 +38,18 @@ RandomAccessHTTP.prototype.open = function (cb) {
35
38
Connection : 'keep-alive'
36
39
}
37
40
} )
38
- var req = this . client . request ( reqOpts , function ( res ) {
41
+ var req = this . client . request ( reqOpts , onres )
42
+
43
+ function onres ( res ) {
39
44
if ( res . statusCode !== 200 ) return cb ( new Error ( 'Bad response: ' + res . statusCode ) )
40
45
if ( headersInvalid ( res . headers ) ) {
41
- return cb ( new Error ( "Source doesn' support 'accept-ranges'" ) )
46
+ return cb ( new Error ( "Source doesn't support 'accept-ranges'" ) )
42
47
}
43
48
self . opened = true
44
49
if ( res . headers [ 'content-length' ] ) self . length = res . headers [ 'content-length' ]
45
50
self . emit ( 'open' )
46
51
cb ( )
47
- } )
52
+ }
48
53
49
54
req . on ( 'error' , ( e ) => {
50
55
return cb ( new Error ( `problem with request: ${ e . message } ` ) )
@@ -70,22 +75,57 @@ RandomAccessHTTP.prototype.read = function (offset, length, cb) {
70
75
if ( ! this . readable ) return cb ( new Error ( 'File is not readable' ) )
71
76
72
77
var self = this
78
+
73
79
var buf = Buffer ( length )
74
80
75
81
if ( ! length ) return cb ( null , buf )
76
82
var reqOpts = xtend ( this . urlObj , {
77
83
method : 'HEAD' ,
78
84
headers : {
79
85
Connection : 'keep-alive' ,
80
- 'Accept-Ranges' : ' bytes'
86
+ Range : ` bytes= ${ offset } - ${ offset + length } `
81
87
}
82
88
} )
83
89
84
- function onres ( ) {
85
- // todo
90
+ var req = this . client . request ( reqOpts , onres )
91
+
92
+ req . on ( 'error' , ( e ) => {
93
+ return cb ( new Error ( `problem with read request: ${ e . message } ` ) )
94
+ } )
95
+
96
+ req . end ( )
97
+
98
+ function onres ( res ) {
99
+ if ( res . statusCode !== 206 ) return cb ( new Error ( 'Bad response: ' + res . statusCode ) )
100
+ if ( ! res . headers [ 'content-range' ] ) return cb ( new Error ( 'Server did not return a byte range' ) )
101
+ var expectedRange = `bytes ${ offset } -${ offset + length } /${ self . length } `
102
+ if ( res . headers [ 'content-range' ] !== expectedRange ) return cb ( new Error ( 'Server returned unexpected range: ' + res . headers [ 'content-range' ] ) )
103
+ var limiter = limitStream ( length )
104
+ var concatStream = concat ( onBuf )
105
+
106
+ pump ( res , limiter , concatStream , function ( err ) {
107
+ if ( err ) return cb ( new Error ( `problem while reading stream: ${ err } ` ) )
108
+ } )
109
+ }
110
+
111
+ function onBuf ( buf ) {
112
+ return cb ( null , buf )
86
113
}
87
114
}
88
115
116
+ // function parseRangeHeader (rangeHeader) {
117
+ // var range = {}
118
+ // var byteRangeArr = rangeHeader.split(' ')
119
+ // range.unit = byteRangeArr[0]
120
+ // var ranges = byteRangeArr[1].split('/')
121
+ // range.totalLength = ranges[1]
122
+ // var startStop = ranges[0].split('-')
123
+ // range.offset = startStop[0]
124
+ // range.end = startStop[1]
125
+ // range.length = range.end - range.offset
126
+ // return range
127
+ // }
128
+
89
129
RandomAccessHTTP . prototype . close = function ( cb ) {
90
130
this . opened = false
91
131
this . emit ( 'close' )
0 commit comments