Created
August 27, 2018 21:48
-
-
Save nkatsaros/34300e220dc509b0cc7fa1858e74b085 to your computer and use it in GitHub Desktop.
Gophercon Sympatico Gokit Exercise
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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