reprose

Basic Go package server
git clone _git@git.zakaria.org/reprose.git
Log | Files | Refs | README

main.go (3124B)


      1 package main
      2 
      3 import (
      4 	"bufio"
      5 	"fmt"
      6 	"net/http"
      7 	"os"
      8 	"strings"
      9 )
     10 
     11 const (
     12 	ListenAddr      = "127.0.0.1:8082"
     13 	ReposFile       = "/etc/reprose.txt"
     14 	Title           = "zakaria's golang repo"
     15 	Host            = "go.zakaria.org"
     16 	DefaultRedirect = "https://git.zakaria.org/"
     17 	Head            = `<meta charset="utf-8"><meta content="width=device-width,initial-scale=1" name="viewport"><style>
     18 	                   pre { line-height: calc(100% * 1.1618); font-size: 100% }
     19 	                   body { margin: 1rem auto; max-width: 50rem; font-size: 100%; line-height: calc(100% * 1.618) }
     20 	                   </style>`
     21 )
     22 
     23 type Repo struct {
     24 	Git  string
     25 	Http string
     26 }
     27 
     28 var Repos map[string]Repo
     29 
     30 func readRepos() error {
     31 	Repos = make(map[string]Repo)
     32 	f, err := os.Open(ReposFile)
     33 	if err != nil {
     34 		return err
     35 	}
     36 
     37 	scanner := bufio.NewScanner(f)
     38 	for scanner.Scan() {
     39 		line := scanner.Text()
     40 
     41 		// skip comments
     42 		if strings.HasPrefix(line, "#") {
     43 			continue
     44 		}
     45 
     46 		// split on whitespace
     47 		split := strings.Fields(line)
     48 		if len(split) < 2 {
     49 			return fmt.Errorf("error parsing repos file")
     50 		}
     51 
     52 		// if separate http redirect is specified, use it
     53 		// otherwise, use the git url for redirect
     54 		if len(split) == 3 {
     55 			Repos[split[0]] = Repo{split[1], split[2]}
     56 		} else {
     57 			Repos[split[0]] = Repo{split[1], split[1]}
     58 		}
     59 	}
     60 	return nil
     61 }
     62 
     63 func isGoGet(req *http.Request) bool {
     64 	q := req.URL.Query()
     65 	goget := q.Get("go-get")
     66 	if len(goget) == 0 {
     67 		return false
     68 	}
     69 	if goget == "1" {
     70 		return true
     71 	}
     72 	return false
     73 }
     74 
     75 func printRepo(base string, repo Repo) string {
     76 	return fmt.Sprintf("<a href=\"/%s\" title=\"%s/%s -> %s\">%s/%s</a> ", base, Host, base, repo.Http, Host, base)
     77 }
     78 
     79 func main() {
     80 	readRepos()
     81 	mux := http.NewServeMux()
     82 	mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
     83 		if req.URL.Path == "/" {
     84 			w.Header().Set("Content-Type", "text/html; charset=utf-8")
     85 			fmt.Fprintf(w, "<html><head>")
     86 			fmt.Fprintf(w, "<title>%s</title>", Title)
     87 			fmt.Fprintf(w, "%s", Head)
     88 			fmt.Fprintf(w, "</head><body>")
     89 			fmt.Fprintf(w, "<pre>%s\n\n", Title)
     90 			fmt.Fprintf(w, "Packages:\n")
     91 			for basename, repo := range Repos {
     92 				fmt.Fprintf(w, "&bullet; %s\n", printRepo(basename, repo))
     93 			}
     94 			fmt.Fprintf(w, "</pre>")
     95 			fmt.Fprintf(w, "</body></html>")
     96 
     97 			return
     98 		}
     99 
    100 		for basename, repo := range Repos {
    101 			if req.URL.Path == "/"+basename {
    102 				// if go-get header is not present redirect to http
    103 				if !isGoGet(req) {
    104 					http.Redirect(w, req, repo.Http, http.StatusPermanentRedirect)
    105 					return
    106 				}
    107 
    108 				w.Header().Set("Content-Type", "text/html; charset=utf-8")
    109 				fmt.Fprintf(w, "<html><head>")
    110 				fmt.Fprintf(w, "<title>%s</title>", basename)
    111 				fmt.Fprintf(w, "<meta name=\"go-import\" content=\"%s/%s git %s\">", Host, basename, repo.Git)
    112 				// fmt.Fprintf(w, "<meta name=\"go-source\" content=\"%s/%s _ %s/tree{/dir} %s/tree{/dir}/{file}#n{line}\">", Host, basename, url, url)
    113 				fmt.Fprintf(w, "</head>")
    114 				fmt.Fprintf(w, "<body>go get %s/%s</body>", Host, basename)
    115 				fmt.Fprintf(w, "</html>")
    116 				return
    117 			}
    118 		}
    119 	})
    120 	http.ListenAndServe(ListenAddr, mux)
    121 }