1package http
2
3import (
4 "bytes"
5 "net/http"
6 "time"
7
8 "github.com/gorilla/mux"
9
10 "github.com/git-bug/git-bug/cache"
11 "github.com/git-bug/git-bug/repository"
12)
13
14// implement a http.Handler that will read and server git blob.
15//
16// Expected gorilla/mux parameters:
17// - "repo" : the ref of the repo or "" for the default one
18// - "hash" : the git hash of the file to retrieve
19type gitFileHandler struct {
20 mrc *cache.MultiRepoCache
21}
22
23func NewGitFileHandler(mrc *cache.MultiRepoCache) http.Handler {
24 return &gitFileHandler{mrc: mrc}
25}
26
27func (gfh *gitFileHandler) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
28 var repo *cache.RepoCache
29 var err error
30
31 repoVar := mux.Vars(r)["repo"]
32 switch repoVar {
33 case "":
34 repo, err = gfh.mrc.DefaultRepo()
35 default:
36 repo, err = gfh.mrc.ResolveRepo(repoVar)
37 }
38
39 if err != nil {
40 http.Error(rw, "invalid repo reference", http.StatusBadRequest)
41 return
42 }
43
44 hash := repository.Hash(mux.Vars(r)["hash"])
45 if !hash.IsValid() {
46 http.Error(rw, "invalid git hash", http.StatusBadRequest)
47 return
48 }
49
50 // TODO: this mean that the whole file will be buffered in memory
51 // This can be a problem for big files. There might be a way around
52 // that by implementing a io.ReadSeeker that would read and discard
53 // data when a seek is called.
54 data, err := repo.ReadData(hash)
55 if err != nil {
56 http.Error(rw, err.Error(), http.StatusInternalServerError)
57 return
58 }
59
60 http.ServeContent(rw, r, "", time.Now(), bytes.NewReader(data))
61}