// Handles POST for /verify func (validator accountValidator) AccountValidatorPost(w http.ResponseWriter, req *http.Request) { var transformedRequest bankAccountRequest // Decode the JSON payload if err := json.NewDecoder(req.Body).Decode(&transformedRequest); err != nil { responses.WriteUnprocessableEntity(w) return } // Check that we got an expected format if !transformedRequest.isValid() { message := "Expected a 6 digits sort code and an account number between 6 and 10 digits." responses.WriteMessage(http.StatusBadRequest, "invalid_bank_account", message, w) return } // Create the required bank account b := models.CreateBankAccount(transformedRequest.SortCode, transformedRequest.AccountNumber) // Check if the bank account is valid isValid := validator.resolver.IsValid(b) // Construct and render the final response response := ValidityResponse{ Valid: isValid, SortCode: b.SortCode, AccountNumber: b.AccountNumber, } render.JSON(w, http.StatusOK, response) }
// The middleware handler func (l *Limiter) ServeHTTP(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) { apiKey := req.Header.Get("Api-Key") // Here, in real life, we would typically create a limiter // based on information from the given API key hasher := speedbump.PerMinuteHasher{} limiter := speedbump.NewLimiter(l.redisConnexion, hasher, 5) canAccess, err := limiter.Attempt(apiKey) // Trouble with Redis? if err != nil { respondRedisError(w) return } // Over the rate limit? if !canAccess { responses.WriteMessage(429, "rate_exceeded", "API rate exceeded. Too many requests.", w) return } requestsLeft, err := limiter.Left(apiKey) // Trouble with Redis? if err != nil { respondRedisError(w) return } // Add the number of remaining request as a header w.Header().Set("Api-Remaining", strconv.Itoa(int(requestsLeft))) // Call the next middleware handler next(w, req) }
// Say that we got an error contacting Redis func respondRedisError(w http.ResponseWriter) { responses.WriteMessage(http.StatusInternalServerError, "server_error", "Trouble contacting Redis. Aborting.", w) return }