Open nicolasparada opened 6 years ago
Good stuff, keep it coming!
@nytro04 Good stuff, keep it coming!
👍
how can i test only this part, without the UI
@joshvoll how can i test only this parte, without the UI
Well isn't much of UI. First, I'd make those http handlers methods of a server
struct and move db
inside the struct. So it isn't global anymore.
type server struct {
db *sql.DB
}
// handler creates an http.Handler with predefined routing.
func handler(db *sql.DB) http.Handler {
s := &server{db: db}
mux := http.NewServeMux()
mux.HandleFunc("/some_path", s.someHandler)
return mux
}
// someHandler handles requests on /some_path.
func (s *server) someHandler(w http.ResponseWriter, r *http.Request) {
// Now you can access the database form s.db.
}
func main() {
db, _ := sql.Open("postgres", "...")
h := handler(db)
http.ListenAndServe(":3000", h)
}
That way you can use a diferent db for testing.
And goind beyond by separating the domain from the http transport layer. Something like:
type Service interface {
GithubOAuthURL(state string) string
UpsertGithubUser(ctx context.Context, code string) (User, error)
Token(userID string) (string, time.Time, error)
}
// service should implement the Service interface.
type service struct {
origin *url.URL
db *sql.DB
githubOAuth *oauth2.Config
tokenSigner jwt.Signer
}
And make use of the service in the handlers. So the http handlers just decode requests and encode responses.
type handler struct {
s Service
}
func Handler(s Service) http.Handler {
h := &handler{s: s}
r := way.NewRouter()
r.HandleFunc("GET", "/api/oauth/github", h.startGithubOAuth)
r.HandleFunc("GET", "/api/oauth/github/callback", h.endGithubOAuth)
return r
}
func (h *handler) startGithubOAuth(w http.ResponseWriter, r *http.Request) {
state, _ := gonanoid.Nanoid()
// TODO: save state.
http.Redirect(w, r, h.s.GithubOAuthURL(state), http.StatusFound)
}
func (h *handler) endGithubOAuth(w http.ResponseWriter, r *http.Request) {
q := r.URL.Query()
// TODO: check state and handle errors.
ctx := r.Context()
u, _ := h.s.UpsertGithubUser(ctx, q.Get("code"))
t, exp, err := h.s.Token(u.ID)
expiresAt, _ := exp.MarshalText()
data := make(url.Values)
data.Set("token", t)
data.Set("expires_at", string(expiresAt))
http.Redirect(w, r, "/callback?"+data.Encode(), http.StatusFound)
}
And you can easily test the service.
thanks a lot, well done
https://nicolasparada.netlify.com/posts/go-messenger-oauth/
Building a Messenger App: OAuth