This repository has been archived on 2022-05-25. You can view files and clone it, but cannot push or open issues or pull requests.
elon-eats-my-tweets/httpserver/httpserver.go

96 lines
2.5 KiB
Go
Raw Normal View History

2022-05-19 19:51:12 +00:00
package httpserver
import (
2022-05-19 20:35:00 +00:00
"context"
2022-05-19 23:03:11 +00:00
"fmt"
2022-05-19 19:51:12 +00:00
"log"
"net/http"
"path/filepath"
"text/template"
"git.netflux.io/rob/elon-eats-my-tweets/config"
2022-05-19 23:03:11 +00:00
"github.com/go-chi/chi"
"github.com/go-chi/chi/middleware"
2022-05-19 19:51:12 +00:00
"golang.org/x/oauth2"
)
type handler struct {
2022-05-19 23:03:11 +00:00
templates *template.Template
2022-05-19 19:51:12 +00:00
oauth2Config *oauth2.Config
}
2022-05-19 23:03:11 +00:00
func newHandler(cfg config.Config, templates *template.Template) *handler {
2022-05-19 19:51:12 +00:00
return &handler{
2022-05-19 23:03:11 +00:00
templates: templates,
oauth2Config: &oauth2.Config{
2022-05-19 19:51:12 +00:00
ClientID: cfg.Twitter.ClientID,
ClientSecret: cfg.Twitter.ClientSecret,
RedirectURL: cfg.Twitter.CallbackURL,
Scopes: []string{"tweet.read", "tweet.write", "users.read", "offline.access"},
Endpoint: oauth2.Endpoint{
AuthURL: "https://twitter.com/i/oauth2/authorize",
2022-05-19 20:35:00 +00:00
TokenURL: "https://api.twitter.com/2/oauth2/token",
2022-05-19 19:51:12 +00:00
},
},
}
}
2022-05-19 23:03:11 +00:00
func (h *handler) getIndex(w http.ResponseWriter, r *http.Request) {
if err := h.templates.ExecuteTemplate(w, "index", nil); err != nil {
log.Printf("error rendering template: %v", err)
http.Error(w, "error rendering template", http.StatusInternalServerError)
return
}
2022-05-19 19:51:12 +00:00
}
2022-05-19 23:03:11 +00:00
func (h *handler) getLogin(w http.ResponseWriter, r *http.Request) {
2022-05-19 19:51:12 +00:00
url := h.oauth2Config.AuthCodeURL(
2022-05-19 20:35:00 +00:00
// TODO: implement state and code_challenge tokens
2022-05-19 19:51:12 +00:00
"state",
oauth2.SetAuthURLParam("code_challenge", "challenge"),
oauth2.SetAuthURLParam("code_challenge_method", "plain"),
)
2022-05-19 23:03:11 +00:00
http.Redirect(w, r, url, http.StatusTemporaryRedirect)
2022-05-19 19:51:12 +00:00
}
2022-05-19 23:03:11 +00:00
func (h *handler) getCallback(w http.ResponseWriter, r *http.Request) {
code := r.URL.Query().Get("code")
2022-05-19 20:35:00 +00:00
if code == "" {
2022-05-19 23:03:11 +00:00
http.Error(w, "empty code", http.StatusBadRequest)
return
2022-05-19 20:35:00 +00:00
}
_, err := h.oauth2Config.Exchange(context.Background(), code, oauth2.SetAuthURLParam("code_verifier", "challenge"))
if err != nil {
log.Printf("error exchanging code: %v", err)
2022-05-19 23:03:11 +00:00
http.Error(w, "error exchanging code", http.StatusInternalServerError)
return
2022-05-19 20:35:00 +00:00
}
2022-05-19 23:03:11 +00:00
w.WriteHeader(http.StatusOK)
w.Header().Set("content-type", "text/html")
if _, err = w.Write([]byte("ok")); err != nil {
log.Printf("error writing response: %v", err)
}
2022-05-19 19:51:12 +00:00
}
func Start(cfg config.Config) error {
2022-05-19 23:03:11 +00:00
r := chi.NewRouter()
r.Use(middleware.RequestID)
r.Use(middleware.RealIP)
r.Use(middleware.Logger)
r.Use(middleware.Recoverer)
2022-05-19 19:51:12 +00:00
2022-05-19 23:03:11 +00:00
templates, err := template.ParseGlob(filepath.Join(cfg.PublicPath, "views", "*.html"))
if err != nil {
return fmt.Errorf("error loading templates: %v", err)
2022-05-19 19:51:12 +00:00
}
2022-05-19 23:03:11 +00:00
h := newHandler(cfg, templates)
r.Get("/", h.getIndex)
r.Get("/login", h.getLogin)
r.Get("/callback", h.getCallback)
2022-05-19 19:51:12 +00:00
2022-05-19 23:03:11 +00:00
return http.ListenAndServe(":8000", r)
2022-05-19 19:51:12 +00:00
}