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的更多相关文章
随机推荐
- LeetCode(34)-Palindrome Number
题目: Determine whether an integer is a palindrome. Do this without extra space. 思路: 求一个整数是不是回文树.负数不是, ...
- 《老罗的Android之旅》导读PPT
虽然好几个月没更新博客了,但是老罗一直有在准备可以分享的东西的.除了早前在微博分享Android4.2相关技术之外,这次还特意准备了13个PPT,总结之前所研究过的东西.内容从Android组件设计思 ...
- JS基础速成(三)- DOM(文件对象模型)
.t1 { background-color: #ff8080; width: 1100px; height: 40px } 一.DOM树的基本结构 DOM节点分为三大类:元素节点(标签节点),属性节 ...
- css 字体两端对齐
我想作为一个前端工作者,总会遇到这样的场景,一个表单展示的字段标题有4个字也有2个字的时候,这样子同时存在想展示的美观一点,就需要字体两端对齐了,其实实现方式很简单,我针对其中一种来做下介绍,以后方法 ...
- MFC学习问题总结
1.学习MFC添加位图,无法获取其ID 1).点击视图->其他窗口->资源视图,你会发现“无法在此窗口显示”,找到resource.h文件,关闭即可重新走一遍上面的过程就会发现可以打开了. ...
- 使用nginx缓存服务器上的静态文件
一.nginx缓存的优点 如图所示,nginx缓存,可以在一定程度上,减少源服务器的处理请求压力. 因为静态文件(比如css,js, 图片)中,很多都是不经常更新的.nginx使用proxy_cach ...
- JavaScript路线
看到知乎上有大神回答的,感觉很不错,分享下 首先要说明的是,咱现在不是高手,最多还是一个半桶水,算是入了JS的门. 谈不上经验,都是一些教训. 这个时候有人要说,“靠,你丫半桶水,凭啥教我们”.您先别 ...
- Python测试远程端口连接时间
问题 最近自己服务器访问别人的服务器,有时候会报超时错误,有时候又能够正常访问别人服务器. 思路 最开始猜测是网络不稳定造成的,但是自己没有收集什么时候超时,什么时候能正常访问别人服务器的日志,搞网络 ...
- 老司机告诉你高质量的Java代码是怎么练成的?
一提起程序员,首先想到的一定是"码农",对,我们是高产量的优质"码农",我们拥有超跃常人的逻辑思维以及不走寻常路的分析.判别能力,当然,我们也有良好的编码规范, ...
- 浅谈java中的"=="和eqals区别
在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str2 = new String(&qu ...