stream-length.coffee
2.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
Promise = require "bluebird"
fs = Promise.promisifyAll(require "fs")
nodeifyWrapper = (callback, func) ->
func().nodeify(callback)
createRetrieverPromise = (stream, retriever) ->
new Promise (resolve, reject) ->
retriever stream, (result) ->
if result?
if result instanceof Error
reject result
else
resolve result
else
reject new Error("Could not find a length using this lengthRetriever.")
retrieveBuffer = (stream, callback) ->
if stream instanceof Buffer
callback stream.length
else
callback null
retrieveFilesystemStream = (stream, callback) ->
if stream.hasOwnProperty "fd"
# FIXME: https://github.com/joyent/node/issues/7819
if stream.end != undefined and stream.end != Infinity and stream.start != undefined
# A stream start and end were defined, we can calculate the size just from that information.
callback(stream.end + 1 - (stream.start ? 0))
else
# We have the start offset at most, stat the file and work off the filesize.
Promise.try ->
fs.statAsync stream.path
.then (stat) ->
callback(stat.size - (stream.start ? 0))
.catch (err) ->
callback err
else
callback null
retrieveCoreHttpStream = (stream, callback) ->
if stream.hasOwnProperty("httpVersion") and stream.headers["content-length"]?
callback parseInt(stream.headers["content-length"])
else
callback null
retrieveRequestHttpStream = (stream, callback) ->
if stream.hasOwnProperty "httpModule"
stream.on "response", (response) ->
if response.headers["content-length"]?
callback parseInt(response.headers["content-length"])
else
callback null
else
callback null
retrieveCombinedStream = (stream, callback) ->
if stream.getCombinedStreamLength?
stream.getCombinedStreamLength()
.then (length) -> callback(length)
.catch (err) -> callback(err)
else
callback null
module.exports = (stream, options = {}, callback) ->
nodeifyWrapper callback, ->
retrieverPromises = []
if options.lengthRetrievers?
# First, the custom length retrievers, if any.
for retriever in options.lengthRetrievers
retrieverPromises.push createRetrieverPromise(stream, retriever)
# Then, the standard ones.
for retriever in [retrieveBuffer, retrieveFilesystemStream, retrieveCoreHttpStream, retrieveRequestHttpStream, retrieveCombinedStream]
retrieverPromises.push createRetrieverPromise(stream, retriever)
Promise.any retrieverPromises