1package http
 2
 3import (
 4	"bytes"
 5	"net/http"
 6	"time"
 7
 8	"github.com/gorilla/mux"
 9
10	"github.com/MichaelMure/git-bug/cache"
11	"github.com/MichaelMure/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 he 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}