minor changes
This commit is contained in:
parent
d61374b9e2
commit
0e18e4202b
3 changed files with 111 additions and 111 deletions
|
|
@ -68,6 +68,6 @@ Environment="PORT=<port>"
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
</code></pre><p>Then start the service:</p><pre><code>sudo systemctl enable docs.brut
|
</code></pre><p>Then start the service:</p><pre><code>sudo systemctl enable docs.brut
|
||||||
sudo systemctl start docs.brut
|
sudo systemctl start docs.brut
|
||||||
</code></pre><h2>Usage Within Git.Brut.Systems</h2><p>Those with repositories on <a href="https://git.brut.systems">git.brut.systems</a> can serve websites by creating a <code>docs/</code> folder (on the default branch). While any file from the repository can be accessed, files within <code>docs/</code> are accessible from <code>/</code>. If a file within <code>docs/</code> conflicts with another file in the repository, the file in <code>docs/</code> take precedence.</p>
|
</code></pre><h2>Usage Within Git.Brut.Systems</h2><p>Those with repositories on <a href="https://git.brut.systems">git.brut.systems</a> can serve websites by creating a <code>docs/</code> folder (on the default branch). While any file from the repository can be accessed, files within <code>docs/</code> are accessible from <code>/</code>. If a <a href="/main.go">file</a> within <code>docs/</code> conflicts with another file in the repository, the file in <code>docs/</code> take precedence.</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -46,4 +46,4 @@ Then start the service:
|
||||||
|
|
||||||
USAGE WITHIN GIT.BRUT.SYSTEMS
|
USAGE WITHIN GIT.BRUT.SYSTEMS
|
||||||
|
|
||||||
Those with repositories on [https://git.brut.systems git.brut.systems] can serve websites by creating a `docs/` folder (on the default branch). While any file from the repository can be accessed, files within `docs/` are accessible from `/`. If a file within `docs/` conflicts with another file in the repository, the file in `docs/` take precedence.
|
Those with repositories on [https://git.brut.systems git.brut.systems] can serve websites by creating a `docs/` folder (on the default branch). While any file from the repository can be accessed, files within `docs/` are accessible from `/`. If a [/main.go file] within `docs/` conflicts with another file in the repository, the file in `docs/` take precedence.
|
||||||
|
|
|
||||||
222
main.go
222
main.go
|
|
@ -21,38 +21,104 @@ var (
|
||||||
PORT string
|
PORT string
|
||||||
)
|
)
|
||||||
|
|
||||||
type Server struct {
|
func main() {
|
||||||
http.ServeMux
|
var err error
|
||||||
|
if API_URL, err = GetEnvironmentVariable("API_URL"); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
} else {
|
||||||
|
if _, err := url.Parse(API_URL); err != nil {
|
||||||
|
log.Fatalf("invalid API_URL %q", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sv *Server) getfile(user, repo, path string) ([]byte, error) {
|
if !strings.HasPrefix(API_URL, "http") {
|
||||||
var (
|
log.Fatalf("invalid API_URL %q - must being with http(s)://", API_URL)
|
||||||
endpoint = endpoint("/repos/%s/%s/contents/%s", user, repo, url.PathEscape(path))
|
}
|
||||||
)
|
}
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", endpoint, nil)
|
if REDIRECT_URL, err = GetEnvironmentVariable("REDIRECT_URL"); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
} else {
|
||||||
|
if _, err := url.Parse(REDIRECT_URL); err != nil {
|
||||||
|
log.Fatalf("invalid REDIRECT_URL %q", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.HasPrefix(REDIRECT_URL, "http") {
|
||||||
|
log.Fatalf("invalid REDIRECT_URL %q - must begin with \"http(s)://\"", REDIRECT_URL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if token, err := GetEnvironmentVariable("API_TOKEN"); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
} else {
|
||||||
|
API_TOKEN = "token " + token
|
||||||
|
}
|
||||||
|
|
||||||
|
if PORT, err = GetEnvironmentVariable("PORT"); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
} else {
|
||||||
|
if _, err = strconv.ParseInt(PORT, 10, 64); err != nil {
|
||||||
|
log.Fatalf("invalid port number %q", PORT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
redirect := func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
http.Redirect(w, r, REDIRECT_URL, http.StatusTemporaryRedirect)
|
||||||
|
}
|
||||||
|
|
||||||
|
sv := new(http.ServeMux)
|
||||||
|
sv.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
redirect(w, r)
|
||||||
|
})
|
||||||
|
sv.HandleFunc("/{user}/{repo}/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
user := strings.TrimSpace(r.PathValue("user"))
|
||||||
|
repo := strings.TrimSpace(r.PathValue("repo"))
|
||||||
|
|
||||||
|
if len(user) == 0 || len(repo) == 0 {
|
||||||
|
redirect(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
path := r.URL.Path
|
||||||
|
path = strings.TrimSpace(path[strings.Index(path, repo)+len(repo):])
|
||||||
|
path = strings.TrimPrefix(path, "/")
|
||||||
|
|
||||||
|
if len(path) == 0 {
|
||||||
|
path = "docs/index.html"
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("fetching file content %s:%s - %q", user, repo, path)
|
||||||
|
|
||||||
|
content, err := FetchFile(user, repo, path)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
redirect(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := w.Write(content); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
redirect(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
addr := fmt.Sprintf(":%s", PORT)
|
||||||
|
log.Printf("Listening at %s", addr)
|
||||||
|
|
||||||
|
if err := http.ListenAndServe(addr, sv); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func FetchFile(user, repo, path string) ([]byte, error) {
|
||||||
|
api_endpoint := FormatEndpoint("/repos/%s/%s/contents/%s", user, repo, url.PathEscape(path))
|
||||||
|
body, status, err := ApiGet(api_endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
req.Header.Add("accept", "application/json")
|
if status != http.StatusOK {
|
||||||
req.Header.Add("Authorization", API_TOKEN)
|
return nil, fmt.Errorf("response had unexpected status %d - %s", status, string(body))
|
||||||
|
|
||||||
log.Printf("GET %q", endpoint)
|
|
||||||
|
|
||||||
var client http.Client
|
|
||||||
res, err := client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
body, err := io.ReadAll(res.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if res.StatusCode != http.StatusOK {
|
|
||||||
return nil, fmt.Errorf("response had unexpected status %d - %s", res.StatusCode, string(body))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var response struct {
|
var response struct {
|
||||||
|
|
@ -77,97 +143,31 @@ func (sv *Server) getfile(user, repo, path string) ([]byte, error) {
|
||||||
return file, nil
|
return file, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func ApiGet(endpoint string) ([]byte, int, error) {
|
||||||
var err error
|
req, err := http.NewRequest("GET", endpoint, nil)
|
||||||
if API_URL, err = getvar("API_URL"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
} else {
|
|
||||||
if _, err := url.Parse(API_URL); err != nil {
|
|
||||||
log.Fatalf("invalid API_URL %q", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !strings.HasPrefix(API_URL, "http") {
|
|
||||||
log.Fatalf("invalid API_URL %q - must being with http(s)://", API_URL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if REDIRECT_URL, err = getvar("REDIRECT_URL"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
} else {
|
|
||||||
if _, err := url.Parse(REDIRECT_URL); err != nil {
|
|
||||||
log.Fatalf("invalid REDIRECT_URL %q", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !strings.HasPrefix(REDIRECT_URL, "http") {
|
|
||||||
log.Fatalf("invalid REDIRECT_URL %q - must begin with \"http(s)://\"", REDIRECT_URL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if token, err := getvar("API_TOKEN"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
} else {
|
|
||||||
API_TOKEN = "token " + token
|
|
||||||
}
|
|
||||||
|
|
||||||
if PORT, err = getvar("PORT"); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
} else {
|
|
||||||
if _, err = strconv.ParseInt(PORT, 10, 64); err != nil {
|
|
||||||
log.Fatalf("invalid port number %q", PORT)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
redirect := func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
http.Redirect(w, r, REDIRECT_URL, http.StatusTemporaryRedirect)
|
|
||||||
}
|
|
||||||
|
|
||||||
sv := new(Server)
|
|
||||||
sv.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
redirect(w, r)
|
|
||||||
})
|
|
||||||
|
|
||||||
sv.HandleFunc("/{user}/{repo}/", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
user := strings.TrimSpace(r.PathValue("user"))
|
|
||||||
repo := strings.TrimSpace(r.PathValue("repo"))
|
|
||||||
|
|
||||||
if len(user) == 0 || len(repo) == 0 {
|
|
||||||
redirect(w, r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
path := r.URL.Path
|
|
||||||
path = strings.TrimSpace(path[strings.Index(path, repo)+len(repo):])
|
|
||||||
path = strings.TrimPrefix(path, "/")
|
|
||||||
|
|
||||||
if len(path) == 0 {
|
|
||||||
path = "docs/index.html"
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("fetching file content %s:%s - %q", user, repo, path)
|
|
||||||
|
|
||||||
content, err := sv.getfile(user, repo, path)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
return nil, -1, err
|
||||||
redirect(w, r)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := w.Write(content); err != nil {
|
req.Header.Add("accept", "application/json")
|
||||||
log.Println(err)
|
req.Header.Add("Authorization", API_TOKEN)
|
||||||
redirect(w, r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
addr := fmt.Sprintf(":%s", PORT)
|
var client http.Client
|
||||||
log.Printf("Listening at %s", addr)
|
log.Printf("GET %q", endpoint)
|
||||||
|
res, err := client.Do(req)
|
||||||
if err := http.ListenAndServe(addr, sv); err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
return nil, -1, err
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getvar(name string) (string, error) {
|
body, err := io.ReadAll(res.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, -1, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return body, res.StatusCode, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetEnvironmentVariable(name string) (string, error) {
|
||||||
envvar := strings.TrimSpace(os.Getenv(name))
|
envvar := strings.TrimSpace(os.Getenv(name))
|
||||||
if len(envvar) == 0 {
|
if len(envvar) == 0 {
|
||||||
return "", fmt.Errorf("required environment variable %q was not set", name)
|
return "", fmt.Errorf("required environment variable %q was not set", name)
|
||||||
|
|
@ -175,7 +175,7 @@ func getvar(name string) (string, error) {
|
||||||
return envvar, nil
|
return envvar, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func endpoint(endpoint string, args ...any) string {
|
func FormatEndpoint(endpoint string, args ...any) string {
|
||||||
url, _ := url.JoinPath(API_URL, "api/v1", fmt.Sprintf(endpoint, args...))
|
url, _ := url.JoinPath(API_URL, "api/v1", fmt.Sprintf(endpoint, args...))
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue