diff --git a/proxy.go b/proxy.go index a274a5d..066c5c5 100644 --- a/proxy.go +++ b/proxy.go @@ -303,6 +303,111 @@ func redirect_handler(w http.ResponseWriter, req *http.Request, string_keys ...s } +func getpart_handler(w http.ResponseWriter, req *http.Request, string_keys ...string) Reply { + if proxy.bctl.Conf.Proxy.RedirectPort == 0 || proxy.bctl.Conf.Proxy.RedirectPort >= 65536 { + err := errors.NewKeyError(req.URL.String(), http.StatusServiceUnavailable, + fmt.Sprintf("redirect is not allowed because of invalid redirect port %d", + proxy.bctl.Conf.Proxy.RedirectPort)) + + return Reply { + err: err, + status: errors.ErrorStatus(err), + } + } + + bname := string_keys[0] + key := string_keys[1] + + reply, err := proxy.bctl.Lookup(bname, key, req) + if err != nil { + return Reply { + err: err, + status: errors.ErrorStatus(err), + } + } + + srv := reply.Servers[rand.Intn(len(reply.Servers))] + + if len(srv.Filename) == 0 { + err := errors.NewKeyError(req.URL.String(), http.StatusServiceUnavailable, + fmt.Sprintf("lookup returned invalid filename: %s", srv.Filename)) + + return Reply { + err: err, + status: errors.ErrorStatus(err), + } + } + + filename := srv.Filename + + if len(proxy.bctl.Conf.Proxy.RedirectRoot) != 0 { + if strings.HasPrefix(filename, proxy.bctl.Conf.Proxy.RedirectRoot) { + filename = filename[len(proxy.bctl.Conf.Proxy.RedirectRoot):] + } + } + + rangeSize := req.Header.Get("Range") + + if (rangeSize != "") { + a := strings.Split(rangeSize, "-") + + + if (a[0] != "0") { + repl := strings.Replace(a[0], "bytes=","", -1) + a[0] = repl + } + + stG,err := strconv.ParseInt(a[0], 10, 32) + if (err != nil) { + stG = 0 + } + + endG,err1 := strconv.ParseInt(a[1], 10, 32) + if (err1 !=nil) { + endG = 0 + } + + st := int(stG) + end := int(endG) + + if (end == 0) { + end = int(srv.Size)-1 + } + + size := st + end + + outEnd := strconv.Itoa(end) + fullSize := strconv.Itoa(int(srv.Size)) + + if (st == 0 && end != 0) { + size = end+1 + } else { + size = (end - st) + 1 + } + + settedSize := strconv.Itoa(size) + settedOffset := strconv.Itoa(st) + + values := req.URL.Query() + values.Add("size", settedSize) + values.Add("offset", settedOffset) + req.URL.RawQuery = values.Encode() + w.Header().Set("Content-Range","bytes "+settedOffset+"-"+outEnd+"/"+fullSize) + w.WriteHeader(http.StatusPartialContent) + } + + err2 := proxy.bctl.Stream(bname, key, w, req) + if err2 != nil { + return Reply { + err: err2, + status: errors.ErrorStatus(err2), + } + } + + return GoodReply() +} + + func delete_handler(w http.ResponseWriter, req *http.Request, strings ...string) Reply { bucket := strings[0] key := strings[1] @@ -542,6 +647,11 @@ var proxy_handlers = map[string]*handler { Methods: []string{"GET"}, Function: get_handler, }, + "getpart": &handler{ + Params: 2, + Methods: []string{"GET"}, + Function: getpart_handler, + }, "lookup": &handler{ Params: 2, Methods: []string{"GET"},