Last active
September 25, 2019 09:19
-
-
Save zeyneloz/64fe8d9291de8554147ae399acc20b83 to your computer and use it in GitHub Desktop.
This file contains 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
package main | |
import ( | |
"encoding/json" | |
"fmt" | |
"io/ioutil" | |
"log" | |
"net/http" | |
) | |
type loginSchema struct { | |
Username string `json:"username"` | |
Password string `json:"password"` | |
} | |
// Return `true`, nil if given user and password exists in database. | |
func loginUser(username string, password string) (bool, error) {...} | |
// Use as a wrapper around the handler functions. | |
type rootHandler func(http.ResponseWriter, *http.Request) error | |
func loginHandler(w http.ResponseWriter, r *http.Request) error { | |
if r.Method != http.MethodPost { | |
return NewHTTPError(nil, 405, "Method not allowed.") | |
} | |
body, err := ioutil.ReadAll(r.Body) // Read request body. | |
if err != nil { | |
return fmt.Errorf("Request body read error : %v", err) | |
} | |
// Parse body as json. | |
var schema loginSchema | |
if err = json.Unmarshal(body, &schema); err != nil { | |
return NewHTTPError(err, 400, "Bad request : invalid JSON.") | |
} | |
ok, err := loginUser(schema.Username, schema.Password) | |
if err != nil { | |
return fmt.Errorf("loginUser DB error : %v", err) | |
} | |
if !ok { // Authentication failed. | |
return NewHTTPError(nil, 401, "Wrong password or username.") | |
} | |
w.WriteHeader(200) // Successfully authenticated. Return access token? | |
return nil | |
} | |
// rootHandler implements http.Handler interface. | |
func (fn rootHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { | |
err := fn(w, r) // Call handler function | |
if err == nil { | |
return | |
} | |
// This is where our error handling logic starts. | |
log.Printf("An error accured: %v", err) // Log the error. | |
clientError, ok := err.(ClientError) // Check if it is a ClientError. | |
if !ok { | |
// If the error is not ClientError, assume that it is ServerError. | |
w.WriteHeader(500) // return 500 Internal Server Error. | |
return | |
} | |
body, err := clientError.ResponseBody() // Try to get response body of ClientError. | |
if err != nil { | |
log.Printf("An error accured: %v", err) | |
w.WriteHeader(500) | |
return | |
} | |
status, headers := clientError.ResponseHeaders() // Get http status code and headers. | |
for k, v := range headers { | |
w.Header().Set(k, v) | |
} | |
w.WriteHeader(status) | |
w.Write(body) | |
} | |
func main() { | |
// Notice rootHandler. | |
http.Handle("/login/", rootHandler(loginHandler)) | |
log.Fatal(http.ListenAndServe(":8080", nil)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment