this repo has no description
1package knotserver
2
3import (
4 "context"
5 "encoding/json"
6 "fmt"
7 "log"
8 "net/http"
9
10 "github.com/go-chi/chi/v5"
11 tangled "github.com/icyphox/bild/api/tangled"
12 "github.com/icyphox/bild/knotserver/config"
13 "github.com/icyphox/bild/knotserver/db"
14 "github.com/icyphox/bild/knotserver/jsclient"
15)
16
17type Handle struct {
18 c *config.Config
19 db *db.DB
20 js *jsclient.JetstreamClient
21}
22
23func Setup(ctx context.Context, c *config.Config, db *db.DB) (http.Handler, error) {
24 r := chi.NewRouter()
25
26 h := Handle{
27 c: c,
28 db: db,
29 }
30
31 err := h.StartJetstream(ctx)
32 if err != nil {
33 return nil, fmt.Errorf("failed to start jetstream: %w", err)
34 }
35
36 r.Get("/", h.Index)
37 r.Route("/{did}", func(r chi.Router) {
38 // Repo routes
39 r.Route("/{name}", func(r chi.Router) {
40 r.Get("/", h.RepoIndex)
41 r.Get("/info/refs", h.InfoRefs)
42 r.Post("/git-upload-pack", h.UploadPack)
43
44 r.Route("/tree/{ref}", func(r chi.Router) {
45 r.Get("/*", h.RepoTree)
46 })
47
48 r.Route("/blob/{ref}", func(r chi.Router) {
49 r.Get("/*", h.FileContent)
50 })
51
52 r.Get("/log/{ref}", h.Log)
53 r.Get("/archive/{file}", h.Archive)
54 r.Get("/commit/{ref}", h.Diff)
55 r.Get("/refs/", h.Refs)
56 })
57 })
58
59 r.Route("/repo", func(r chi.Router) {
60 r.Put("/new", h.NewRepo)
61 })
62
63 r.With(h.VerifySignature).Get("/health", h.Health)
64
65 r.Group(func(r chi.Router) {
66 r.Use(h.VerifySignature)
67 r.Get("/keys", h.Keys)
68 r.Put("/keys", h.Keys)
69 })
70
71 return r, nil
72}
73
74func (h *Handle) StartJetstream(ctx context.Context) error {
75 colections := []string{tangled.PublicKeyNSID}
76 dids := []string{}
77
78 h.js = jsclient.NewJetstreamClient(colections, dids)
79 messages, err := h.js.ReadJetstream(ctx)
80 if err != nil {
81 return fmt.Errorf("failed to read from jetstream: %w", err)
82 }
83
84 go func() {
85 for msg := range messages {
86 var data map[string]interface{}
87 if err := json.Unmarshal(msg, &data); err != nil {
88 log.Printf("error unmarshaling message: %v", err)
89 continue
90 }
91
92 if kind, ok := data["kind"].(string); ok && kind == "commit" {
93 log.Printf("commit event: %+v", data)
94 }
95 }
96 }()
97
98 log.Printf("started jetstream")
99
100 return nil
101}
102
103func (h *Handle) Multiplex(w http.ResponseWriter, r *http.Request) {
104 path := chi.URLParam(r, "*")
105
106 if r.URL.RawQuery == "service=git-receive-pack" {
107 w.WriteHeader(http.StatusBadRequest)
108 w.Write([]byte("no pushing allowed!"))
109 return
110 }
111
112 fmt.Println(r.URL.RawQuery)
113 fmt.Println(r.Method)
114
115 if path == "info/refs" &&
116 r.URL.RawQuery == "service=git-upload-pack" &&
117 r.Method == "GET" {
118 h.InfoRefs(w, r)
119 } else if path == "git-upload-pack" && r.Method == "POST" {
120 h.UploadPack(w, r)
121 } else if r.Method == "GET" {
122 h.RepoIndex(w, r)
123 }
124}