💾 Archived View for gemini.rmf-dev.com › repo › Vaati › Gemigit › files › 2689ad9cd5732be8684dcd47ab… captured on 2022-07-16 at 17:09:35. Gemini links have been rewritten to link to archived content

View Raw

More Information

-=-=-=-=-=-=-

0 package httpgit

1

2 import (

3 "gemigit/db"

4 "log"

5 "net/http"

6 "strconv"

7 "strings"

8 "time"

9

10 githttpxfer "github.com/nulab/go-git-http-xfer/githttpxfer"

11 )

12

13 func Listen(path string, port int) {

14 ghx, err := githttpxfer.New(path, "git")

15 if err != nil {

16 log.Fatalln("GitHTTPXfer instance could not be created. ", err.Error())

17 }

18

19 chain := newChain()

20 chain.use(logging)

21 chain.use(basicAuth)

22 handler := chain.build(ghx)

23

24 log.Println("Http server started on port", port)

25 if err := http.ListenAndServe(":"+strconv.Itoa(port), handler); err != nil {

26 log.Fatalln("ListenAndServe: ", err.Error())

27 }

28 }

29

30 type middleware func(http.Handler) http.Handler

31

32 func newChain() *chain {

33 return &chain{[]middleware{}}

34 }

35

36 type chain struct {

37 middlewares []middleware

38 }

39

40 func (c *chain) use(m middleware) {

41 c.middlewares = append(c.middlewares, m)

42 }

43

44 func (c *chain) build(h http.Handler) http.Handler {

45 for i := range c.middlewares {

46 h = c.middlewares[len(c.middlewares)-1-i](h)

47 }

48 return h

49 }

50

51 func logging(next http.Handler) http.Handler {

52 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

53 t1 := time.Now()

54 next.ServeHTTP(w, r)

55 t2 := time.Now()

56 realIP := r.Header.Get("X-Real-IP")

57 log.Println("["+realIP+"]["+r.Method+"]", r.URL.String(), t2.Sub(t1))

58 })

59 }

60

61 func basicAuth(next http.Handler) http.Handler {

62 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

63 params := strings.Split(r.URL.Path[1:], "/")

64 if len(params) < 2 {

65 renderNotFound(w)

66 return

67 }

68 if strings.Contains(r.URL.Path, "git-upload-pack") || strings.Contains(r.URL.RawQuery, "git-upload-pack") {

69 b, err := db.IsRepoPublic(params[1], params[0])

70 if err != nil {

71 renderNotFound(w)

72 return

73 }

74 if b {

75 next.ServeHTTP(w, r)

76 return

77 }

78 }

79 username, password, ok := r.BasicAuth()

80 if !ok {

81 renderUnauthorized(w)

82 return

83 }

84 ok, err := db.CheckAuth(username, password)

85 if err != nil {

86 log.Println(err.Error())

87 }

88 if !ok || err != nil {

89 renderUnauthorized(w)

90 return

91 }

92 next.ServeHTTP(w, r)

93 })

94 }

95

96 func renderNotFound(w http.ResponseWriter) {

97 w.WriteHeader(http.StatusNotFound)

98 w.Write([]byte(http.StatusText(http.StatusNotFound)))

99 w.Header().Set("Content-Type", "text/plain")

100 }

101

102 func renderUnauthorized(w http.ResponseWriter) {

103 w.Header().Set("WWW-Authenticate", `Basic realm="Please enter your username and password."`)

104 w.WriteHeader(http.StatusUnauthorized)

105 w.Write([]byte(http.StatusText(http.StatusUnauthorized)))

106 w.Header().Set("Content-Type", "text/plain")

107 }

108