home to your local SPACEGIRL 💫 arimelody.space
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

slowly but surely fixing routing and layout handling

Signed-off-by: ari melody <ari@arimelody.me>

+80 -170
+24 -11
api/v1/admin/admin.go
··· 2 2 3 3 import ( 4 4 "context" 5 - "encoding/json" 6 5 "fmt" 7 6 "math/rand" 8 7 "net/http" 9 - "net/url" 10 8 "os" 11 9 "strings" 12 10 "time" 13 11 14 12 "arimelody.me/arimelody.me/discord" 13 + "arimelody.me/arimelody.me/global" 15 14 ) 16 15 17 16 type ( 18 17 Session struct { 19 18 UserID string 20 19 Token string 21 - } 22 - 23 - loginData struct { 24 - UserID string 25 - Password string 20 + Expires int64 26 21 } 27 22 ) 28 23 ··· 45 40 return Session{ 46 41 UserID: UserID, 47 42 Token: string(generateToken()), 43 + Expires: time.Now().Add(24 * time.Hour).Unix(), 48 44 } 49 45 } 50 46 51 47 func Handler() http.Handler { 52 - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 53 - fmt.Println(r.URL.Path) 48 + mux := http.NewServeMux() 54 49 50 + mux.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 55 51 w.WriteHeader(200) 56 - w.Write([]byte("hello admin!")) 57 - }) 52 + w.Write([]byte("hello /admin!")) 53 + })) 54 + mux.Handle("/callback", global.HTTPLog(OAuthCallbackHandler())) 55 + mux.Handle("/login", global.HTTPLog(LoginHandler())) 56 + mux.Handle("/verify", global.HTTPLog(AuthorisedHandler(VerifyHandler()))) 57 + mux.Handle("/logout", global.HTTPLog(AuthorisedHandler(LogoutHandler()))) 58 + 59 + return mux 58 60 } 59 61 60 62 func AuthorisedHandler(next http.Handler) http.Handler { ··· 73 75 74 76 var session *Session 75 77 for _, s := range sessions { 78 + if s.Expires < time.Now().Unix() { 79 + // expired session. remove it from the list! 80 + new_sessions := []*Session{} 81 + for _, ns := range sessions { 82 + if ns.Token == s.Token { 83 + continue 84 + } 85 + new_sessions = append(new_sessions, ns) 86 + } 87 + continue 88 + } 76 89 if s.Token == auth { 77 90 session = s 78 91 break
+36 -11
global/global.go
··· 1 1 package global 2 2 3 3 import ( 4 + "fmt" 4 5 "net/http" 6 + "strconv" 5 7 "time" 6 8 ) 7 9 8 10 var LAST_MODIFIED = time.Now() 9 11 10 - var MimeTypes = map[string]string{ 11 - "css": "text/css; charset=utf-8", 12 - "png": "image/png", 13 - "jpg": "image/jpg", 14 - "webp": "image/webp", 15 - "html": "text/html", 16 - "asc": "text/plain", 17 - "pub": "text/plain", 18 - "js": "application/javascript", 19 - } 20 - 21 12 func IsModified(req *http.Request, last_modified time.Time) bool { 22 13 if len(req.Header["If-Modified-Since"]) == 0 || len(req.Header["If-Modified-Since"][0]) == 0 { 23 14 return true ··· 32 23 return false 33 24 } 34 25 26 + type loggingResponseWriter struct { 27 + http.ResponseWriter 28 + code int 29 + } 30 + 31 + func (lw *loggingResponseWriter) WriteHeader(code int) { 32 + lw.code = code 33 + lw.ResponseWriter.WriteHeader(code) 34 + } 35 + 36 + func HTTPLog(next http.Handler) http.Handler { 37 + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 38 + start := time.Now() 39 + 40 + lw := loggingResponseWriter{w, http.StatusOK} 41 + 42 + next.ServeHTTP(&lw, r) 43 + 44 + after := time.Now() 45 + difference := (after.Nanosecond() - start.Nanosecond()) / 1_000_000 46 + elapsed := "<1" 47 + if difference >= 1 { 48 + elapsed = strconv.Itoa(difference) 49 + } 50 + 51 + fmt.Printf("[%s] %s %s - %d (%sms) (%s)\n", 52 + after.Format(time.UnixDate), 53 + r.Method, 54 + r.URL.Path, 55 + lw.code, 56 + elapsed, 57 + r.Header["User-Agent"][0]) 58 + }) 59 + }
+17 -145
main.go
··· 5 5 "html/template" 6 6 "log" 7 7 "net/http" 8 - "strconv" 9 - "time" 8 + "path/filepath" 10 9 11 10 "arimelody.me/arimelody.me/api/v1/admin" 12 11 "arimelody.me/arimelody.me/api/v1/music" 12 + "arimelody.me/arimelody.me/global" 13 13 ) 14 14 15 15 const DEFAULT_PORT int = 8080 16 16 17 - var base_template = template.Must(template.ParseFiles( 18 - "views/base.html", 19 - "views/header.html", 20 - "views/footer.html", 21 - "views/prideflag.html", 22 - )) 23 - 24 - func log_request(req *http.Request, code int, start_time time.Time) { 25 - now := time.Now() 26 - difference := (now.Nanosecond() - start_time.Nanosecond()) / 1_000_000 27 - elapsed := "<1" 28 - if difference >= 1 { 29 - elapsed = strconv.Itoa(difference) 30 - } 31 - 32 - fmt.Printf("[%s] %s %s - %d (%sms) (%s)\n", 33 - now.Format(time.UnixDate), 34 - req.Method, 35 - req.URL.Path, 36 - code, 37 - elapsed, 38 - req.Header["User-Agent"][0]) 39 - } 40 - 41 - // func handle_request(res http.ResponseWriter, req *http.Request) { 42 - // uri := req.URL.Path 43 - // start_time := time.Now() 44 - // 45 - // res.Header().Set("Server", "arimelody.me") 46 - // 47 - // code := func(res http.ResponseWriter, req *http.Request) int { 48 - // var root = template.Must(base_template.Clone()) 49 - // 50 - // if req.URL.Path == "/" { 51 - // return handle_index(res, req, root) 52 - // } 53 - // 54 - // if uri == "/music" || uri == "/music/" { 55 - // return handle_music(res, req, root) 56 - // } 57 - // 58 - // if strings.HasPrefix(uri, "/music/") { 59 - // return handle_music_gateway(res, req, root) 60 - // } 61 - // 62 - // if strings.HasPrefix(uri, "/admin") { 63 - // return admin.Handle(res, req, root) 64 - // } 65 - // 66 - // if strings.HasPrefix(uri, "/api") { 67 - // return api.Handle(res, req, root) 68 - // } 69 - // 70 - // return static_handler(res, req, root) 71 - // }(res, req) 72 - // 73 - // log_request(req, code, start_time) 74 - // } 75 - // 76 - // func handle_index(res http.ResponseWriter, req *http.Request, root *template.Template) int { 77 - // if !global.IsModified(req, global.LAST_MODIFIED) { 78 - // res.WriteHeader(304) 79 - // return 304 80 - // } 81 - // 82 - // index_template := template.Must(root.ParseFiles("views/index.html")) 83 - // err := index_template.Execute(res, nil) 84 - // if err != nil { 85 - // http.Error(res, err.Error(), http.StatusInternalServerError) 86 - // return 500 87 - // } 88 - // return 200 89 - // } 90 - // 91 17 // func handle_music(res http.ResponseWriter, req *http.Request, root *template.Template) int { 92 18 // if !global.IsModified(req, global.LAST_MODIFIED) { 93 19 // res.WriteHeader(304) ··· 102 28 // } 103 29 // return 200 104 30 // } 105 - // 31 + 106 32 // func handle_music_gateway(res http.ResponseWriter, req *http.Request, root *template.Template) int { 107 33 // if !global.IsModified(req, global.LAST_MODIFIED) { 108 34 // res.WriteHeader(304) ··· 122 48 // } 123 49 // return 200 124 50 // } 125 - // 126 - // func static_handler(res http.ResponseWriter, req *http.Request, root *template.Template) int { 127 - // filename := "public/" + req.URL.Path[1:] 128 - // 129 - // // check the file's metadata 130 - // info, err := os.Stat(filename) 131 - // if err != nil { 132 - // return handle_not_found(res, req, root) 133 - // } 134 - // 135 - // if !global.IsModified(req, info.ModTime()) { 136 - // res.WriteHeader(304) 137 - // return 304 138 - // } 139 - // 140 - // // set Last-Modified to file modification date 141 - // res.Header().Set("Last-Modified", info.ModTime().Format(http.TimeFormat)) 142 - // 143 - // // read the file 144 - // body, err := os.ReadFile(filename) 145 - // if err != nil { 146 - // http.Error(res, err.Error(), http.StatusInternalServerError) 147 - // return 500 148 - // } 149 - // 150 - // // setting MIME types 151 - // filetype := filename[strings.LastIndex(filename, ".")+1:] 152 - // if mime_type, ok := global.MimeTypes[filetype]; ok { 153 - // res.Header().Set("Content-Type", mime_type) 154 - // } else { 155 - // res.Header().Set("Content-Type", "text/plain; charset=utf-8") 156 - // } 157 - // 158 - // res.Write([]byte(body)) 159 - // return 200 160 - // } 161 - // 162 - // func handle_not_found(res http.ResponseWriter, req *http.Request, root *template.Template) int { 163 - // type ErrorData struct { 164 - // Target string 165 - // } 166 - // error_data := ErrorData{ Target: req.URL.Path } 167 - // res.WriteHeader(404); 168 - // error_template := template.Must(root.ParseFiles("views/404.html")) 169 - // err := error_template.Execute(res, error_data) 170 - // if err != nil { 171 - // http.Error(res, err.Error(), http.StatusInternalServerError) 172 - // return 500 173 - // } 174 - // return 404 175 - // } 176 - // 177 - // func parse_markdown(md []byte) []byte { 178 - // extensions := parser.CommonExtensions | parser.AutoHeadingIDs | parser.NoEmptyLineBeforeBlock 179 - // p := parser.NewWithExtensions(extensions) 180 - // doc := p.Parse(md) 181 - // 182 - // htmlFlags := html.CommonFlags 183 - // opts := html.RendererOptions{Flags: htmlFlags} 184 - // renderer := html.NewRenderer(opts) 185 - // 186 - // return markdown.Render(doc, renderer) 187 - // } 188 51 189 52 func main() { 190 53 db := InitDatabase() ··· 204 67 205 68 mux := http.NewServeMux() 206 69 207 - mux.Handle("/api/v1/admin", admin.Handler()) 208 - mux.Handle("/api/v1/admin/login", admin.LoginHandler()) 209 - mux.Handle("/api/v1/admin/callback", admin.OAuthCallbackHandler()) 210 - mux.Handle("/api/v1/admin/verify", admin.AuthorisedHandler(admin.VerifyHandler())) 211 - mux.Handle("/api/v1/admin/logout", admin.AuthorisedHandler(admin.LogoutHandler())) 70 + mux.Handle("/api/v1/admin/", global.HTTPLog(http.StripPrefix("/api/v1/admin", admin.Handler()))) 71 + mux.Handle("/", http.FileServer(http.Dir("./public"))) 72 + // mux.Handle("/", global.HTTPLog(http.HandlerFunc(serveTemplate))) 212 73 213 74 port := DEFAULT_PORT 214 75 fmt.Printf("now serving at http://127.0.0.1:%d\n", port) 215 76 log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", port), mux)) 216 77 } 78 + 79 + func serveTemplate(w http.ResponseWriter, r *http.Request) { 80 + lp_base := filepath.Join("views", "layout.html") 81 + lp_header := filepath.Join("views", "header.html") 82 + lp_footer := filepath.Join("views", "footer.html") 83 + lp_prideflag := filepath.Join("views", "prideflag.html") 84 + fp := filepath.Join("views", filepath.Clean(r.URL.Path)) 85 + 86 + template, _ := template.ParseFiles(lp_base, lp_header, lp_footer, lp_prideflag, fp) 87 + template.ExecuteTemplate(w, "layout", nil) 88 + }
+3 -3
schema.sql
··· 19 19 CREATE TABLE IF NOT EXISTS musiclinks ( 20 20 release character varying(64) NOT NULL, 21 21 name text NOT NULL, 22 - url text, 22 + url text 23 23 ); 24 24 ALTER TABLE musiclinks ADD CONSTRAINT musiclinks_pk PRIMARY KEY (release, name); 25 25 ··· 27 27 release character varying(64) NOT NULL, 28 28 artist text NOT NULL, 29 29 role text, 30 - is_primary boolean, 30 + is_primary boolean 31 31 ); 32 32 ALTER TABLE musiccredits ADD CONSTRAINT musiccredits_pk PRIMARY KEY (release, artist); 33 33 ··· 37 37 title text NOT NULL, 38 38 description text, 39 39 lyrics text, 40 - preview_url text, 40 + preview_url text 41 41 ); 42 42 ALTER TABLE musictracks ADD CONSTRAINT musictracks_pk PRIMARY KEY (release, number); 43 43
views/base.html views/layout.html