all repos — flounder @ 9cae990bcac0b7990cfe3f57f1d5fc5c14969e3e

A small site builder for the Gemini protocol

http.go (view raw)

  1package main
  2
  3import (
  4	"html/template"
  5	"log"
  6	"net/http"
  7	"path"
  8	"strings"
  9)
 10
 11var t *template.Template
 12
 13// TODO somewhat better error handling
 14const InternalServerErrorMsg = "500: Internal Server Error"
 15
 16func renderError(w http.ResponseWriter, errorMsg string, statusCode int) { // TODO think about pointers
 17	data := struct{ ErrorMsg string }{errorMsg}
 18	err := t.ExecuteTemplate(w, "error.html", data)
 19	if err != nil { // shouldn't happen probably
 20		http.Error(w, errorMsg, statusCode)
 21	}
 22}
 23
 24func indexHandler(w http.ResponseWriter, r *http.Request) {
 25	indexFiles, err := getIndexFiles()
 26	if err != nil {
 27		log.Println(err)
 28		renderError(w, InternalServerErrorMsg, 500)
 29		return
 30	}
 31	allUsers, err := getUsers()
 32	if err != nil {
 33		log.Println(err)
 34		renderError(w, InternalServerErrorMsg, 500)
 35		return
 36	}
 37	data := struct {
 38		Domain    string
 39		PageTitle string
 40		Files     []*File
 41		Users     []string
 42	}{c.RootDomain, c.SiteTitle, indexFiles, allUsers}
 43	err = t.ExecuteTemplate(w, "index.html", data)
 44	if err != nil {
 45		log.Println(err)
 46		renderError(w, InternalServerErrorMsg, 500)
 47		return
 48	}
 49
 50}
 51
 52func editFileHandler(w http.ResponseWriter, r *http.Request) {
 53	// read file content. create if dne
 54	// authUser := "alex"
 55	data := struct {
 56		FileName  string
 57		FileText  string
 58		PageTitle string
 59	}{"filename", "filetext", c.SiteTitle}
 60	err := t.ExecuteTemplate(w, "edit_file.html", data)
 61	if err != nil {
 62		log.Println(err)
 63		renderError(w, InternalServerErrorMsg, 500)
 64		return
 65	}
 66}
 67
 68func mySiteHandler(w http.ResponseWriter, r *http.Request) {
 69	authUser := "alex"
 70	// check auth
 71	files, _ := getUserFiles(authUser)
 72	data := struct {
 73		Domain    string
 74		PageTitle string
 75		AuthUser  string
 76		Files     []*File
 77	}{c.RootDomain, c.SiteTitle, authUser, files}
 78	_ = t.ExecuteTemplate(w, "my_site.html", data)
 79}
 80
 81func loginHandler(w http.ResponseWriter, r *http.Request) {
 82	if r.Method == "GET" {
 83		// show page
 84		data := struct {
 85			Error     string
 86			PageTitle string
 87		}{"", c.SiteTitle}
 88		err := t.ExecuteTemplate(w, "login.html", data)
 89		if err != nil {
 90			log.Println(err)
 91			renderError(w, InternalServerErrorMsg, 500)
 92			return
 93		}
 94	} else if r.Method == "POST" {
 95		r.ParseForm()
 96		name := r.Form.Get("username")
 97		password := r.Form.Get("password")
 98		err := checkAuth(name, password)
 99		if err == nil {
100			log.Println("logged in")
101			// redirect home
102		} else {
103			data := struct {
104				Error     string
105				PageTitle string
106			}{"Invalid login or password", c.SiteTitle}
107			err := t.ExecuteTemplate(w, "login.html", data)
108			if err != nil {
109				log.Println(err)
110				renderError(w, InternalServerErrorMsg, 500)
111				return
112			}
113		}
114		// create session
115		// redirect home
116		// verify login
117		// check for errors
118	}
119}
120
121func register(w http.ResponseWriter, r *http.Request) {
122	if r.Method == "GET" {
123	} else if r.Method == "POST" {
124	}
125}
126
127// Server a user's file
128func userFile(w http.ResponseWriter, r *http.Request) {
129	userName := strings.Split(r.Host, ".")[0]
130	fileName := path.Join(c.FilesDirectory, userName, r.URL.Path)
131	// if gemini -- parse, convert, serve
132	// else
133	http.ServeFile(w, r, fileName)
134}
135
136func runHTTPServer() {
137	log.Println("Running http server")
138	var err error
139	t, err = template.ParseGlob("./templates/*.html") // TODO make template dir configruable
140	if err != nil {
141		log.Fatal(err)
142	}
143	http.HandleFunc(c.RootDomain+"/", indexHandler)
144	http.HandleFunc(c.RootDomain+"/my_site", mySiteHandler)
145	http.HandleFunc(c.RootDomain+"/edit/", editFileHandler)
146	http.HandleFunc(c.RootDomain+"/login", loginHandler)
147	// http.HandleFunc("/delete/", deleteFileHandler)
148	// login+register functions
149
150	// handle user files based on subdomain
151	http.HandleFunc("/", userFile)
152	log.Fatal(http.ListenAndServe(":8080", logRequest(http.DefaultServeMux)))
153}
154
155func logRequest(handler http.Handler) http.Handler {
156	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
157		log.Printf("%s %s %s\n", r.RemoteAddr, r.Method, r.URL)
158		handler.ServeHTTP(w, r)
159	})
160}