forked from tangled.org/core
this repo has no description

appview: proxy clones to knot

Changed files
+93 -6
appview
+85
appview/state/git_http.go
···
+
package state
+
+
import (
+
"fmt"
+
"io"
+
"net/http"
+
+
"github.com/bluesky-social/indigo/atproto/identity"
+
"github.com/go-chi/chi/v5"
+
)
+
+
func (s *State) InfoRefs(w http.ResponseWriter, r *http.Request) {
+
user := r.Context().Value("resolvedId").(identity.Identity)
+
knot := r.Context().Value("knot").(string)
+
repo := chi.URLParam(r, "repo")
+
+
// TODO: make this https for production!
+
targetURL := fmt.Sprintf("http://%s/%s/%s/info/refs?%s", knot, user.DID, repo, r.URL.RawQuery)
+
resp, err := http.Get(targetURL)
+
if err != nil {
+
http.Error(w, err.Error(), http.StatusInternalServerError)
+
return
+
}
+
defer resp.Body.Close()
+
+
// Copy response headers
+
for k, v := range resp.Header {
+
w.Header()[k] = v
+
}
+
+
// Set response status code
+
w.WriteHeader(resp.StatusCode)
+
+
// Copy response body
+
if _, err := io.Copy(w, resp.Body); err != nil {
+
http.Error(w, err.Error(), http.StatusInternalServerError)
+
return
+
}
+
+
}
+
+
func (s *State) UploadPack(w http.ResponseWriter, r *http.Request) {
+
user, ok := r.Context().Value("resolvedId").(identity.Identity)
+
if !ok {
+
http.Error(w, "failed to resolve user", http.StatusInternalServerError)
+
return
+
}
+
knot := r.Context().Value("knot").(string)
+
repo := chi.URLParam(r, "repo")
+
// TODO: make this https for production!
+
targetURL := fmt.Sprintf("http://%s/%s/%s/git-upload-pack?%s", knot, user.DID, repo, r.URL.RawQuery)
+
client := &http.Client{}
+
+
// Create new request
+
proxyReq, err := http.NewRequest(r.Method, targetURL, r.Body)
+
if err != nil {
+
http.Error(w, err.Error(), http.StatusInternalServerError)
+
return
+
}
+
+
// Copy original headers
+
proxyReq.Header = r.Header
+
+
// Execute request
+
resp, err := client.Do(proxyReq)
+
if err != nil {
+
http.Error(w, err.Error(), http.StatusInternalServerError)
+
return
+
}
+
defer resp.Body.Close()
+
+
// Copy response headers
+
for k, v := range resp.Header {
+
w.Header()[k] = v
+
}
+
+
// Set response status code
+
w.WriteHeader(resp.StatusCode)
+
+
// Copy response body
+
if _, err := io.Copy(w, resp.Body); err != nil {
+
http.Error(w, err.Error(), http.StatusInternalServerError)
+
return
+
}
+
}
+2 -2
appview/state/middleware.go
···
})
}
-
func ResolveRepoDomain(s *State) Middleware {
+
func ResolveRepoKnot(s *State) Middleware {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
repoName := chi.URLParam(req, "repo")
···
return
}
-
ctx := context.WithValue(req.Context(), "domain", repo.Knot)
+
ctx := context.WithValue(req.Context(), "knot", repo.Knot)
next.ServeHTTP(w, req.WithContext(ctx))
})
}
+2 -2
appview/state/repo.go
···
ctx := r.Context()
repoName := chi.URLParam(r, "repo")
-
domain, ok := ctx.Value("domain").(string)
+
knot, ok := ctx.Value("knot").(string)
if !ok {
log.Println("malformed middleware")
w.WriteHeader(http.StatusInternalServerError)
···
return
}
-
resp, err := http.Get(fmt.Sprintf("http://%s/%s/%s", domain, id.DID.String(), repoName))
+
resp, err := http.Get(fmt.Sprintf("http://%s/%s/%s", knot, id.DID.String(), repoName))
if err != nil {
log.Println("failed to reach knotserver", err)
return
+4 -2
appview/state/state.go
···
r.With(ResolveIdent).Route("/{user}", func(r chi.Router) {
r.Get("/", s.ProfilePage)
-
r.With(ResolveRepoDomain(s)).Route("/{repo}", func(r chi.Router) {
+
r.With(ResolveRepoKnot(s)).Route("/{repo}", func(r chi.Router) {
r.Get("/", s.RepoIndex)
-
// r.Get("/info/refs", s.InfoRefs)
+
// These routes get proxied to the knot
+
r.Get("/info/refs", s.InfoRefs)
+
r.Post("/git-upload-pack", s.UploadPack)
})
})