Skip to content

Instantly share code, notes, and snippets.

@nkatsaros
Created August 27, 2018 21:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nkatsaros/34300e220dc509b0cc7fa1858e74b085 to your computer and use it in GitHub Desktop.
Save nkatsaros/34300e220dc509b0cc7fa1858e74b085 to your computer and use it in GitHub Desktop.
Gophercon Sympatico Gokit Exercise
diff --git a/internal/auth/http_server.go b/internal/auth/http_server.go
index a2f993d..0b55ffb 100644
--- a/internal/auth/http_server.go
+++ b/internal/auth/http_server.go
@@ -1,9 +1,12 @@
package auth
import (
+ "context"
"fmt"
"net/http"
+ kithttp "github.com/go-kit/kit/transport/http"
+
"github.com/gorilla/mux"
)
@@ -20,10 +23,26 @@ func NewHTTPServer(service *Service) *HTTPServer {
}
r := mux.NewRouter()
{
- r.Methods("POST").Path("/signup").HandlerFunc(s.handleSignup)
- r.Methods("POST").Path("/login").HandlerFunc(s.handleLogin)
- r.Methods("GET").Path("/validate").HandlerFunc(s.handleValidate)
- r.Methods("POST").Path("/logout").HandlerFunc(s.handleLogout)
+ r.Methods("POST").Path("/signup").Handler(kithttp.NewServer(
+ makeSignupEndpoint(service),
+ decodeSignupRequest,
+ encodeSignupResponse,
+ ))
+ r.Methods("POST").Path("/login").Handler(kithttp.NewServer(
+ makeLoginEndpoint(service),
+ decodeLoginRequest,
+ encodeLoginResponse,
+ ))
+ r.Methods("GET").Path("/validate").Handler(kithttp.NewServer(
+ makeValidateEndpoint(service),
+ decodeValidateRequest,
+ encodeValidateResponse,
+ ))
+ r.Methods("POST").Path("/logout").Handler(kithttp.NewServer(
+ makeLogoutEndpoint(service),
+ decodeLogoutRequest,
+ encodeLogoutResponse,
+ ))
}
s.router = r
return s
@@ -34,61 +53,86 @@ func (s *HTTPServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
s.router.ServeHTTP(w, r)
}
-func (s *HTTPServer) handleSignup(w http.ResponseWriter, r *http.Request) {
- var (
- user = r.URL.Query().Get("user")
- pass = r.URL.Query().Get("pass")
- )
- if err := s.service.Signup(r.Context(), user, pass); err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
+func decodeSignupRequest(_ context.Context, r *http.Request) (interface{}, error) {
+ request := signupRequest{
+ User: r.URL.Query().Get("user"),
+ Pass: r.URL.Query().Get("pass"),
+ }
+ return request, nil
+}
+
+func encodeSignupResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
+ resp := response.(signupResponse)
+ if resp.Err != nil {
+ http.Error(w, resp.Err.Error(), http.StatusInternalServerError)
+ return nil
}
fmt.Fprintln(w, "signup successful")
+ return nil
+}
+
+func decodeLoginRequest(_ context.Context, r *http.Request) (interface{}, error) {
+ request := loginRequest{
+ User: r.URL.Query().Get("user"),
+ Pass: r.URL.Query().Get("pass"),
+ }
+ return request, nil
}
-func (s *HTTPServer) handleLogin(w http.ResponseWriter, r *http.Request) {
- var (
- user = r.URL.Query().Get("user")
- pass = r.URL.Query().Get("pass")
- )
- token, err := s.service.Login(r.Context(), user, pass)
- if err == ErrBadAuth {
- http.Error(w, err.Error(), http.StatusUnauthorized)
- return
+func encodeLoginResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
+ resp := response.(loginResponse)
+ if resp.Err == ErrBadAuth {
+ http.Error(w, resp.Err.Error(), http.StatusUnauthorized)
+ return nil
}
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
+ if resp.Err != nil {
+ http.Error(w, resp.Err.Error(), http.StatusInternalServerError)
+ return nil
}
- fmt.Fprintln(w, token)
+ fmt.Fprintln(w, resp.Token)
+ return nil
}
-func (s *HTTPServer) handleValidate(w http.ResponseWriter, r *http.Request) {
- var (
- user = r.URL.Query().Get("user")
- token = r.URL.Query().Get("token")
- )
- err := s.service.Validate(r.Context(), user, token)
- if err != nil {
- http.Error(w, err.Error(), http.StatusUnauthorized)
- return
+func decodeValidateRequest(_ context.Context, r *http.Request) (interface{}, error) {
+ request := validateRequest{
+ User: r.URL.Query().Get("user"),
+ Token: r.URL.Query().Get("token"),
+ }
+ return request, nil
+}
+
+func encodeValidateResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
+ resp := response.(validateResponse)
+ if resp.Err == ErrBadAuth {
+ http.Error(w, resp.Err.Error(), http.StatusUnauthorized)
+ return nil
+ }
+ if resp.Err != nil {
+ http.Error(w, resp.Err.Error(), http.StatusInternalServerError)
+ return nil
}
fmt.Fprintln(w, "validate successful")
+ return nil
+}
+
+func decodeLogoutRequest(_ context.Context, r *http.Request) (interface{}, error) {
+ request := logoutRequest{
+ User: r.URL.Query().Get("user"),
+ Token: r.URL.Query().Get("token"),
+ }
+ return request, nil
}
-func (s *HTTPServer) handleLogout(w http.ResponseWriter, r *http.Request) {
- var (
- user = r.URL.Query().Get("user")
- token = r.URL.Query().Get("token")
- )
- err := s.service.Logout(r.Context(), user, token)
- if err == ErrBadAuth {
- http.Error(w, err.Error(), http.StatusUnauthorized)
- return
+func encodeLogoutResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
+ resp := response.(logoutResponse)
+ if resp.Err == ErrBadAuth {
+ http.Error(w, resp.Err.Error(), http.StatusUnauthorized)
+ return nil
}
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
+ if resp.Err != nil {
+ http.Error(w, resp.Err.Error(), http.StatusInternalServerError)
+ return nil
}
fmt.Fprintln(w, "logout successful")
+ return nil
}
diff --git a/internal/auth/service.go b/internal/auth/service.go
index 3d73f8a..c8f4c5f 100644
--- a/internal/auth/service.go
+++ b/internal/auth/service.go
@@ -4,6 +4,7 @@ import (
"context"
"fmt"
+ "github.com/go-kit/kit/endpoint"
"github.com/prometheus/client_golang/prometheus"
"github.com/peterbourgon/sympatico/internal/ctxlog"
@@ -44,6 +45,26 @@ func (s *Service) Signup(ctx context.Context, user, pass string) (err error) {
return s.repo.Create(ctx, user, pass)
}
+type signupRequest struct {
+ User string
+ Pass string
+}
+
+type signupResponse struct {
+ Err error
+}
+
+func makeSignupEndpoint(svc *Service) endpoint.Endpoint {
+ return func(ctx context.Context, request interface{}) (interface{}, error) {
+ req := request.(signupRequest)
+ err := svc.Signup(ctx, req.User, req.Pass)
+ if err != nil {
+ return signupResponse{err}, nil
+ }
+ return signupResponse{nil}, nil
+ }
+}
+
// Login logs the user in, if the pass is correct.
// The returned token should be passed to Logout or Validate.
func (s *Service) Login(ctx context.Context, user, pass string) (token string, err error) {
@@ -54,6 +75,27 @@ func (s *Service) Login(ctx context.Context, user, pass string) (token string, e
return s.repo.Auth(ctx, user, pass)
}
+type loginRequest struct {
+ User string
+ Pass string
+}
+
+type loginResponse struct {
+ Token string
+ Err error
+}
+
+func makeLoginEndpoint(svc *Service) endpoint.Endpoint {
+ return func(ctx context.Context, request interface{}) (interface{}, error) {
+ req := request.(loginRequest)
+ v, err := svc.Login(ctx, req.User, req.Pass)
+ if err != nil {
+ return loginResponse{v, err}, nil
+ }
+ return loginResponse{v, nil}, nil
+ }
+}
+
// Logout logs the user out, if the token is valid.
func (s *Service) Logout(ctx context.Context, user, token string) (err error) {
defer func() {
@@ -63,6 +105,26 @@ func (s *Service) Logout(ctx context.Context, user, token string) (err error) {
return s.repo.Deauth(ctx, user, token)
}
+type logoutRequest struct {
+ User string
+ Token string
+}
+
+type logoutResponse struct {
+ Err error
+}
+
+func makeLogoutEndpoint(svc *Service) endpoint.Endpoint {
+ return func(ctx context.Context, request interface{}) (interface{}, error) {
+ req := request.(logoutRequest)
+ err := svc.Logout(ctx, req.User, req.Token)
+ if err != nil {
+ return logoutResponse{err}, nil
+ }
+ return logoutResponse{nil}, nil
+ }
+}
+
// Validate returns a nil error if the user is logged in and
// provides the correct token.
func (s *Service) Validate(ctx context.Context, user, token string) (err error) {
@@ -72,3 +134,23 @@ func (s *Service) Validate(ctx context.Context, user, token string) (err error)
}()
return s.repo.Validate(ctx, user, token)
}
+
+type validateRequest struct {
+ User string
+ Token string
+}
+
+type validateResponse struct {
+ Err error
+}
+
+func makeValidateEndpoint(svc *Service) endpoint.Endpoint {
+ return func(ctx context.Context, request interface{}) (interface{}, error) {
+ req := request.(validateRequest)
+ err := svc.Validate(ctx, req.User, req.Token)
+ if err != nil {
+ return validateResponse{err}, nil
+ }
+ return validateResponse{nil}, nil
+ }
+}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment