public_handers.go
package manager
import (
"net/http"
"regexp"
"strconv"
"io"
"strings"
"fmt"
"time"
)
var publicUrlRegex *regexp.Regexp
func init() {
var err error
publicUrlRegex, err = regexp.Compile("/([0-9]*)/([0-9]*)/(.*)")
if err != nil {
panic(err)
}
}
//公共资源处理器
func (vm *VolumeManager)publicEntry(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet, http.MethodHead:
if publicUrlRegex.MatchString(r.URL.Path) {
vm.publicReadFile(w, r)
} else {
http.NotFound(w, r)
}
default:
w.WriteHeader(http.StatusMethodNotAllowed)
}
}
//读取公共资源文件
func (vm *VolumeManager)publicReadFile(w http.ResponseWriter, r *http.Request) {
match := publicUrlRegex.FindStringSubmatch(r.URL.Path)
vid, _ := strconv.ParseUint(match[1], 10, 64)
volume := vm.Volumes[vid]
if volume == nil {
http.Error(w, "can't find volume", http.StatusNotFound)
return
}
fid, _ := strconv.ParseUint(match[2], 10, 64)
file, err := volume.Get(fid)
if err != nil || file.Info.FileName != match[3] {
http.NotFound(w, r)
return
}
w.Header().Set("Content-Type", get_content_type(file.Info.FileName))
w.Header().Set("Accept-Ranges", "bytes")
w.Header().Set("ETag", fmt.Sprintf("\"%d\"", fid))
//暂时不使用Last-Modified,用ETag即可
//w.Header().Set("Last-Modified", file.Info.Mtime.Format(http.TimeFormat))
w.Header().Set("Expires", time.Now().In(time.UTC).Add(DefaultExpires).Format(http.TimeFormat))
etagMatch := false
if r.Header.Get("If-None-Match") != "" {
s := r.Header.Get("If-None-Match")
if etag, err := strconv.ParseUint(s[1:len(s) - 1], 10, 64); err == nil && etag == fid {
etagMatch = true
}
}
if r.Header.Get("Range") != "" {
ranges := strings.Split(r.Header.Get("Range")[6:], "-")
start, err := strconv.ParseUint(ranges[0], 10, 64)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
length := uint64(0)
if start > file.Info.Size {
start = file.Info.Size
} else if ranges[1] != "" {
end, err := strconv.ParseUint(ranges[1], 10, 64)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
end += 1
if end > file.Info.Size {
end = file.Info.Size
}
length = end - start
} else {
length = file.Info.Size - start
}
w.Header().Set("Content-Length", strconv.FormatUint(length, 10))
if length == 0 {
w.WriteHeader(http.StatusRequestedRangeNotSatisfiable)
return
}
w.Header().Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", start, start + length - 1, file.Info.Size))
if etagMatch {
w.WriteHeader(http.StatusNotModified)
return
}
w.WriteHeader(http.StatusPartialContent)
if r.Method != http.MethodHead {
file.Seek(int64(start), 0)
io.CopyN(w, file, int64(length))
}
} else {
w.Header().Set("Content-Length", strconv.FormatUint(file.Info.Size, 10))
if etagMatch {
w.WriteHeader(http.StatusNotModified)
} else if r.Method != http.MethodHead {
io.Copy(w, file)
}
}
}
public_handers.go的更多相关文章
随机推荐
- obj-c编程17:键值观察(KVO)
说完了前面一篇KVC,不能不说说它的应用KVO(Key-Value Observing)喽.KVO类似于ruby里的hook功能,就是当一个对象属性发生变化时,观察者可以跟踪变化,进而观察或是修正这个 ...
- java多继承
众所周知,java面向对象语言中只有单继承的编程语言,也许你会说,通过实现多个接口这种变通的方式达到多继承的目的.没错,你说的对,不过这并不是本片文章要说到的内容,本文要讲到的内容是java中实实在在 ...
- Course2-Python函数和模块
一. 函数 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率. 上一课里提到了Python的很多内置函数.在此主要讲自定义函数. 1. 定 ...
- [转]web服务器压力测试工具
http_load学习心得: 测试网站每秒所能承受的平均访问量(吞吐量) http_load -parallel 5 -fetches 1000 urls.txt这段命令行是同时使用5个进程,随机访问 ...
- (转) windows下 安装 rabbitMQ 及操作常用命令
该博客转载自:https://blog.csdn.net/gy__my/article/details/78295943 原作者:Eric Li 出处:http://www.cnblogs.com/ ...
- Angular集成UEditor
1.Ueditor的集成主要通过把UEditor做成一个Component来实现,先上Component代码: import { AfterContentInit, Component, Input, ...
- Ubuntu下定时任务和自启动任务的部署
1.定时任务的部署,最简单的方法是执行 crontab -e 然后在下面加上世间周期配置和要执行的命令,一般情况下,可以把要执行的任务用bash脚本封装一下,格式如下所示: minute hour ...
- c#与webapi交互
public static string HttpConnectToServer(string ServerPage,string strData) { string postData =strDat ...
- 设计模式的征途—22.中介者(Mediator)模式
我们都用过QQ,它有两种聊天方式:一是私聊,二是群聊.使用QQ群,一个用户就可以向多个用户发送相同的信息和文件,从而无需一一发送,节省大量时间.通过引入群的机制,极大地减少系统中用户之间的两两通信,用 ...
- Python_字符串简单加密解密
def crypt(source,key): from itertools import cycle result='' temp=cycle(key) for ch in source: resul ...