Skip to content

Commit

Permalink
fix(Server): fix range-stream process
Browse files Browse the repository at this point in the history
  • Loading branch information
hans00 committed Aug 3, 2022
1 parent c0605c3 commit d88dd30
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 14 deletions.
16 changes: 13 additions & 3 deletions packages/server/js/response.js
@@ -1,11 +1,10 @@
const ServerError = require('./errors')
const { buildHeaderValue } = require('./utils')
const { buildHeaderValue, rangeStream } = require('./utils')
const fs = require('fs')
const path = require('path')
const mime = require('mime-types')
const { Writable } = require('stream')
const parseRange = require('range-parser')
const rangeStream = require('ranges-stream')

const staticPath = path.resolve(process.cwd(), 'static')

Expand Down Expand Up @@ -271,7 +270,7 @@ class Response extends Writable {
if (this._totalSize && end <= this._totalSize) {
this.status(206)
.setHeader('Content-Range', `bytes ${start}-${end}/${this._totalSize}`)
this._totalSize = end - start
this._totalSize = end - start + 1
return stream.pipe(rangeStream(ranges)).pipe(this)
}
}
Expand Down Expand Up @@ -338,6 +337,17 @@ class Response extends Writable {
return this
}

set (keyOrMap, value) {
if (typeof keyOrMap === 'object') {
for (const [key, val] of Object.entries(keyOrMap)) {
this.setHeader(key, val)
}
} else {
this.setHeader(keyOrMap, value)
}
return this
}

location (loc, code = 302) {
this.setHeader('Location', loc).status(code)
return this
Expand Down
27 changes: 27 additions & 0 deletions packages/server/js/utils.js
@@ -1,4 +1,5 @@
const CIDRMatcher = require('cidr-matcher')
const through = require('through2')

const V4Prefix = Buffer.from([0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff])

Expand Down Expand Up @@ -68,3 +69,29 @@ exports.createCidrMatcher = (CIDRs) =>
.map((rangeOrName) => namedCidrs[rangeOrName] || rangeOrName)
.flat()
)

// Ref: https://github.com/finnp/ranges-stream
exports.rangeStream = (ranges) => {
let pos = 0
let currentRange = ranges.shift()
return through(function processChunk (chunk, enc, cb) {
if (!(currentRange)) return cb()

if (pos + chunk.length > currentRange.start) {
const bufStart = Math.max(currentRange.start - pos, 0)
const bufEnd = currentRange.end - pos + 1
if (currentRange.end <= pos + chunk.length) {
this.push(chunk.slice(bufStart, bufEnd))
currentRange = ranges.shift() // next Range
pos += bufEnd
return processChunk.bind(this)(chunk.slice(bufEnd), enc, cb)
} else {
// the range continues to the next chunk
this.push(bufStart > 0 ? chunk.slice(bufStart) : chunk)
}
}

pos += chunk.length
cb()
})
}
2 changes: 1 addition & 1 deletion packages/server/package.json
Expand Up @@ -44,8 +44,8 @@
"multipart-formdata": "^1.1.0",
"qs": "^6.10.3",
"range-parser": "^1.2.1",
"ranges-stream": "^1.0.0",
"replicator": "^1.0.5",
"through2": "^4.0.2",
"uWebSockets.js": "https://github.com/uNetworking/uWebSockets.js#binaries"
},
"gitHead": "e939a8cb4e569fc3155c95c942470ab279e9d77d"
Expand Down
4 changes: 2 additions & 2 deletions test/cases/http-pipe-file-stream-range.js
Expand Up @@ -3,7 +3,7 @@ const axios = require('axios')
module.exports = async function ({ HTTP_PORT }) {
const res = await axios.get(`http://localhost:${HTTP_PORT}/stream/file`, {
headers: {
Range: 'bytes=0-4'
Range: 'bytes=0-3'
}
})
if (res.status !== 206) {
Expand All @@ -15,7 +15,7 @@ module.exports = async function ({ HTTP_PORT }) {
if (Number(res.headers['content-length']) !== 4) {
throw new Error(`Invalid Content-Length: ${res.headers['content-length']}`)
}
if (!['bytes 0-4/10', 'bytes 0-4/11'].includes(res.headers['content-range'])) {
if (!['bytes 0-3/10', 'bytes 0-3/11'].includes(res.headers['content-range'])) {
throw new Error(`Invalid Content-Range: ${res.headers['content-range']}`)
}
if (res.data !== 'TEST') {
Expand Down
9 changes: 1 addition & 8 deletions yarn.lock
Expand Up @@ -5469,13 +5469,6 @@ range-parser@^1.2.1, range-parser@~1.2.1:
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==

ranges-stream@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/ranges-stream/-/ranges-stream-1.0.0.tgz#7d304c513d6a017018818a9d51e815c8645e9035"
integrity sha512-wQ2WoBcfqJuUVNE09lOHCa12ttGo0kBybgEBqoqw19sISdZh/FD7bpWuwA/5hCm7Z4rcJP5Qwaswk4YZwFkgdw==
dependencies:
through2 "^2.0.0"

raw-body@2.5.1:
version "2.5.1"
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857"
Expand Down Expand Up @@ -6158,7 +6151,7 @@ through2@^2.0.0:
readable-stream "~2.3.6"
xtend "~4.0.1"

through2@^4.0.0:
through2@^4.0.0, through2@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/through2/-/through2-4.0.2.tgz#a7ce3ac2a7a8b0b966c80e7c49f0484c3b239764"
integrity sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==
Expand Down

0 comments on commit d88dd30

Please sign in to comment.