// Logger wraps a handler with basic HTTP logging func Logger( globalContext *context.GlobalContext, ) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { localContext := context.Get(r) localContext.Logger = logger.New() t0 := time.Now() localContext.Logger.WriteString("====\n") localContext.Logger.Printf( "[%s] %s %s", r.Method, r.RemoteAddr, r.URL.String(), ) next.ServeHTTP(w, r) localContext.Logger.Printf("FINISHED IN %v", time.Now().Sub(t0)) loggerMutex.Lock() _, err := localContext.Logger.WriteTo(globalContext.LogOut) loggerMutex.Unlock() if err != nil { panic(err) } }) } }
// Refresh fetches new auth tokens for an existing session that has // expired. func Refresh(globalContext *context.GlobalContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { localContext := context.Get(r) tokens, err := spotify.RefreshAuthTokens( localContext.AuthTokens, globalContext.Spotify.ClientID, globalContext.Spotify.ClientSecret, ) if err != nil { panic(err) } data := map[string]interface{}{ "expires_in": tokens.ExpiresIn, } jsonToken, err := json.Marshal(tokens) if err != nil { panic(err) } token, err := crypto.Encrypt(string(jsonToken)) if err != nil { panic(err) } data["token"] = token w.Header().Set("Content-type", "application/json") err = json.NewEncoder(w).Encode(data) if err != nil { panic(err) } } }
// TokenParser looks for a "token" GET parameter, decrypts and parses // it, and kills the request if anything fails along the way. func TokenParser(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { localContext := context.Get(r) token := r.URL.Query().Get("token") decryptedToken, err := crypto.Decrypt(token) if err != nil { panic(err) } err = json.Unmarshal([]byte(decryptedToken), &localContext.AuthTokens) if err != nil { panic(err) } if localContext.AuthTokens.AccessToken == "" { panic(errors.New("Missing access token")) } if localContext.AuthTokens.RefreshToken == "" { panic(errors.New("Missing refresh token")) } next.ServeHTTP(w, r) }) }
// Submit fires off a goroutine to actually mix the selected playlists // into the destination list with the specified options. func Submit(globalContext *context.GlobalContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { localContext := context.Get(r) userID, err := spotify.GetUserID(localContext.AuthTokens) if err != nil { panic(err) } data := submissionData{} err = json.NewDecoder(r.Body).Decode(&data) if err != nil { panic(err) } go mixPlaylists(globalContext, localContext, userID, data) } }
// Playlists fetches and returns a list of the user's playlists as // JSON. func Playlists(w http.ResponseWriter, r *http.Request) { localContext := context.Get(r) userID, err := spotify.GetUserID(localContext.AuthTokens) if err != nil { panic(err) } playlists, err := spotify.GetPlaylists(localContext.AuthTokens, userID) if err != nil { panic(err) } result := map[string]interface{}{ "userID": userID, "playlists": playlists, } w.Header().Set("Content-type", "application/json") err = json.NewEncoder(w).Encode(result) if err != nil { panic(err) } }