Monorepo for Tangled tangled.org

appview: proxy clones to knot

Changed files
+93 -6
appview
+85
appview/state/git_http.go
··· 1 + package state 2 + 3 + import ( 4 + "fmt" 5 + "io" 6 + "net/http" 7 + 8 + "github.com/bluesky-social/indigo/atproto/identity" 9 + "github.com/go-chi/chi/v5" 10 + ) 11 + 12 + func (s *State) InfoRefs(w http.ResponseWriter, r *http.Request) { 13 + user := r.Context().Value("resolvedId").(identity.Identity) 14 + knot := r.Context().Value("knot").(string) 15 + repo := chi.URLParam(r, "repo") 16 + 17 + // TODO: make this https for production! 18 + targetURL := fmt.Sprintf("http://%s/%s/%s/info/refs?%s", knot, user.DID, repo, r.URL.RawQuery) 19 + resp, err := http.Get(targetURL) 20 + if err != nil { 21 + http.Error(w, err.Error(), http.StatusInternalServerError) 22 + return 23 + } 24 + defer resp.Body.Close() 25 + 26 + // Copy response headers 27 + for k, v := range resp.Header { 28 + w.Header()[k] = v 29 + } 30 + 31 + // Set response status code 32 + w.WriteHeader(resp.StatusCode) 33 + 34 + // Copy response body 35 + if _, err := io.Copy(w, resp.Body); err != nil { 36 + http.Error(w, err.Error(), http.StatusInternalServerError) 37 + return 38 + } 39 + 40 + } 41 + 42 + func (s *State) UploadPack(w http.ResponseWriter, r *http.Request) { 43 + user, ok := r.Context().Value("resolvedId").(identity.Identity) 44 + if !ok { 45 + http.Error(w, "failed to resolve user", http.StatusInternalServerError) 46 + return 47 + } 48 + knot := r.Context().Value("knot").(string) 49 + repo := chi.URLParam(r, "repo") 50 + // TODO: make this https for production! 51 + targetURL := fmt.Sprintf("http://%s/%s/%s/git-upload-pack?%s", knot, user.DID, repo, r.URL.RawQuery) 52 + client := &http.Client{} 53 + 54 + // Create new request 55 + proxyReq, err := http.NewRequest(r.Method, targetURL, r.Body) 56 + if err != nil { 57 + http.Error(w, err.Error(), http.StatusInternalServerError) 58 + return 59 + } 60 + 61 + // Copy original headers 62 + proxyReq.Header = r.Header 63 + 64 + // Execute request 65 + resp, err := client.Do(proxyReq) 66 + if err != nil { 67 + http.Error(w, err.Error(), http.StatusInternalServerError) 68 + return 69 + } 70 + defer resp.Body.Close() 71 + 72 + // Copy response headers 73 + for k, v := range resp.Header { 74 + w.Header()[k] = v 75 + } 76 + 77 + // Set response status code 78 + w.WriteHeader(resp.StatusCode) 79 + 80 + // Copy response body 81 + if _, err := io.Copy(w, resp.Body); err != nil { 82 + http.Error(w, err.Error(), http.StatusInternalServerError) 83 + return 84 + } 85 + }
+2 -2
appview/state/middleware.go
··· 131 131 }) 132 132 } 133 133 134 - func ResolveRepoDomain(s *State) Middleware { 134 + func ResolveRepoKnot(s *State) Middleware { 135 135 return func(next http.Handler) http.Handler { 136 136 return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { 137 137 repoName := chi.URLParam(req, "repo") ··· 150 150 return 151 151 } 152 152 153 - ctx := context.WithValue(req.Context(), "domain", repo.Knot) 153 + ctx := context.WithValue(req.Context(), "knot", repo.Knot) 154 154 next.ServeHTTP(w, req.WithContext(ctx)) 155 155 }) 156 156 }
+2 -2
appview/state/repo.go
··· 14 14 ctx := r.Context() 15 15 repoName := chi.URLParam(r, "repo") 16 16 17 - domain, ok := ctx.Value("domain").(string) 17 + knot, ok := ctx.Value("knot").(string) 18 18 if !ok { 19 19 log.Println("malformed middleware") 20 20 w.WriteHeader(http.StatusInternalServerError) ··· 28 28 return 29 29 } 30 30 31 - resp, err := http.Get(fmt.Sprintf("http://%s/%s/%s", domain, id.DID.String(), repoName)) 31 + resp, err := http.Get(fmt.Sprintf("http://%s/%s/%s", knot, id.DID.String(), repoName)) 32 32 if err != nil { 33 33 log.Println("failed to reach knotserver", err) 34 34 return
+4 -2
appview/state/state.go
··· 599 599 600 600 r.With(ResolveIdent).Route("/{user}", func(r chi.Router) { 601 601 r.Get("/", s.ProfilePage) 602 - r.With(ResolveRepoDomain(s)).Route("/{repo}", func(r chi.Router) { 602 + r.With(ResolveRepoKnot(s)).Route("/{repo}", func(r chi.Router) { 603 603 r.Get("/", s.RepoIndex) 604 - // r.Get("/info/refs", s.InfoRefs) 604 + // These routes get proxied to the knot 605 + r.Get("/info/refs", s.InfoRefs) 606 + r.Post("/git-upload-pack", s.UploadPack) 605 607 }) 606 608 }) 607 609