mirror of
https://github.com/TeaOSLab/EdgeNode.git
synced 2025-11-05 01:20:26 +08:00
128 lines
2.1 KiB
Go
128 lines
2.1 KiB
Go
|
|
package nodes
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"crypto/rand"
|
|||
|
|
"fmt"
|
|||
|
|
"io"
|
|||
|
|
"strconv"
|
|||
|
|
"strings"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// 分解Range
|
|||
|
|
func httpRequestParseContentRange(rangeValue string) (result [][]int, ok bool) {
|
|||
|
|
// 参考RFC:https://tools.ietf.org/html/rfc7233
|
|||
|
|
index := strings.Index(rangeValue, "=")
|
|||
|
|
if index == -1 {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
unit := rangeValue[:index]
|
|||
|
|
if unit != "bytes" {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
rangeSetString := rangeValue[index+1:]
|
|||
|
|
if len(rangeSetString) == 0 {
|
|||
|
|
ok = true
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
pieces := strings.Split(rangeSetString, ", ")
|
|||
|
|
for _, piece := range pieces {
|
|||
|
|
index := strings.Index(piece, "-")
|
|||
|
|
if index == -1 {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
first := piece[:index]
|
|||
|
|
firstInt := -1
|
|||
|
|
|
|||
|
|
var err error
|
|||
|
|
last := piece[index+1:]
|
|||
|
|
var lastInt = -1
|
|||
|
|
|
|||
|
|
if len(first) > 0 {
|
|||
|
|
firstInt, err = strconv.Atoi(first)
|
|||
|
|
if err != nil {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if len(last) > 0 {
|
|||
|
|
lastInt, err = strconv.Atoi(last)
|
|||
|
|
if err != nil {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
if lastInt < firstInt {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
if len(last) == 0 {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
lastInt, err = strconv.Atoi(last)
|
|||
|
|
if err != nil {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
lastInt = -lastInt
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
result = append(result, []int{firstInt, lastInt})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ok = true
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 读取内容Range
|
|||
|
|
func httpRequestReadRange(reader io.Reader, buf []byte, start int, end int, callback func(buf []byte, n int) error) (ok bool, err error) {
|
|||
|
|
if start < 0 || end < 0 {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
seeker, ok := reader.(io.Seeker)
|
|||
|
|
if !ok {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
_, err = seeker.Seek(int64(start), io.SeekStart)
|
|||
|
|
if err != nil {
|
|||
|
|
return false, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
offset := start
|
|||
|
|
for {
|
|||
|
|
n, err := reader.Read(buf)
|
|||
|
|
if n > 0 {
|
|||
|
|
offset += n
|
|||
|
|
if end < offset {
|
|||
|
|
err = callback(buf, n-(offset-end-1))
|
|||
|
|
if err != nil {
|
|||
|
|
return false, err
|
|||
|
|
}
|
|||
|
|
return true, nil
|
|||
|
|
} else {
|
|||
|
|
err = callback(buf, n)
|
|||
|
|
if err != nil {
|
|||
|
|
return false, err
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if err != nil {
|
|||
|
|
if err == io.EOF {
|
|||
|
|
return true, nil
|
|||
|
|
}
|
|||
|
|
return false, err
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 生成boundary
|
|||
|
|
// 仿照Golang自带的函数(multipart包)
|
|||
|
|
func httpRequestGenBoundary() string {
|
|||
|
|
var buf [30]byte
|
|||
|
|
_, err := io.ReadFull(rand.Reader, buf[:])
|
|||
|
|
if err != nil {
|
|||
|
|
panic(err)
|
|||
|
|
}
|
|||
|
|
return fmt.Sprintf("%x", buf[:])
|
|||
|
|
}
|