117 lines
2.5 KiB
Go
117 lines
2.5 KiB
Go
package gitrpc
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
"net/http"
|
|
|
|
"simplegit/common"
|
|
)
|
|
|
|
func (s *Server) authorizeRead(w http.ResponseWriter, r *http.Request, repo string) bool {
|
|
if repo == "" {
|
|
http.Error(w, "missing repo", http.StatusBadRequest)
|
|
return false
|
|
}
|
|
if _, status, msg := s.authorize(r, repo, common.PermRead); status != 0 {
|
|
http.Error(w, msg, status)
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (s *Server) serveRaw(w http.ResponseWriter, r *http.Request) {
|
|
q := r.URL.Query()
|
|
repoName := q.Get("repo")
|
|
if !s.authorizeRead(w, r, repoName) {
|
|
return
|
|
}
|
|
ref := q.Get("ref")
|
|
filePath := q.Get("file")
|
|
|
|
repo, err := s.open(r.Context(), repoName)
|
|
if err != nil {
|
|
writeHTTPError(w, err)
|
|
return
|
|
}
|
|
content, err := repo.GetRawContent(ref, filePath)
|
|
if err != nil {
|
|
http.Error(w, "read file: "+err.Error(), http.StatusNotFound)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/octet-stream")
|
|
_, _ = io.WriteString(w, content)
|
|
}
|
|
|
|
func (s *Server) servePatch(w http.ResponseWriter, r *http.Request) {
|
|
q := r.URL.Query()
|
|
repoName := q.Get("repo")
|
|
if !s.authorizeRead(w, r, repoName) {
|
|
return
|
|
}
|
|
sha := q.Get("sha")
|
|
|
|
repo, err := s.open(r.Context(), repoName)
|
|
if err != nil {
|
|
writeHTTPError(w, err)
|
|
return
|
|
}
|
|
patch, err := repo.Patch(sha)
|
|
if err != nil {
|
|
http.Error(w, "format-patch: "+err.Error(), http.StatusNotFound)
|
|
return
|
|
}
|
|
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
|
_, _ = io.WriteString(w, patch)
|
|
}
|
|
|
|
func (s *Server) serveArchive(w http.ResponseWriter, r *http.Request) {
|
|
q := r.URL.Query()
|
|
repoName := q.Get("repo")
|
|
if !s.authorizeRead(w, r, repoName) {
|
|
return
|
|
}
|
|
ref := q.Get("ref")
|
|
format := q.Get("format")
|
|
|
|
repo, err := s.open(r.Context(), repoName)
|
|
if err != nil {
|
|
writeHTTPError(w, err)
|
|
return
|
|
}
|
|
|
|
if format == "" {
|
|
format = "zip"
|
|
}
|
|
switch format {
|
|
case "zip":
|
|
w.Header().Set("Content-Type", "application/zip")
|
|
case "tar":
|
|
w.Header().Set("Content-Type", "application/x-tar")
|
|
default:
|
|
http.Error(w, "format must be zip or tar", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if err := repo.Archive(ref, format, w); err != nil {
|
|
|
|
http.Error(w, "archive: "+err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
}
|
|
|
|
func writeHTTPError(w http.ResponseWriter, err error) {
|
|
var re *rpcError
|
|
if errors.As(err, &re) {
|
|
switch re.Code {
|
|
case codeRepoNotFound:
|
|
http.Error(w, re.Message, http.StatusNotFound)
|
|
default:
|
|
http.Error(w, re.Message, http.StatusBadRequest)
|
|
}
|
|
return
|
|
}
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
}
|