From 3484e02590117d175d9c1ab24c583390b4e94a55 Mon Sep 17 00:00:00 2001
From: Stephen J Day <stephen.day@docker.com>
Date: Wed, 16 Nov 2016 18:58:55 -0800
Subject: [PATCH] api/server/httputils: ensure consistent status code

Error code resolution is powered by string matching. Not the greatest
thing in the world and I hope no one is proud of this code, but it
works. However, because a map is used, the iteration order of the map is
random, such that if an error matches two of the snippets, it may return
a different error code depending on the seed of the hashmap. This change
converts it to use a slice instead.

Signed-off-by: Stephen J Day <stephen.day@docker.com>
---
 api/server/httputils/errors.go | 29 ++++++++++++++++-------------
 1 file changed, 16 insertions(+), 13 deletions(-)

diff --git a/api/server/httputils/errors.go b/api/server/httputils/errors.go
index d8d49726231b0..6b57f7b8845f0 100644
--- a/api/server/httputils/errors.go
+++ b/api/server/httputils/errors.go
@@ -49,20 +49,23 @@ func GetHTTPErrorStatusCode(err error) int {
 		// If we need to differentiate between different possible error types,
 		// we should create appropriate error types that implement the httpStatusError interface.
 		errStr := strings.ToLower(errMsg)
-		for keyword, status := range map[string]int{
-			"not found":             http.StatusNotFound,
-			"no such":               http.StatusNotFound,
-			"bad parameter":         http.StatusBadRequest,
-			"no command":            http.StatusBadRequest,
-			"conflict":              http.StatusConflict,
-			"impossible":            http.StatusNotAcceptable,
-			"wrong login/password":  http.StatusUnauthorized,
-			"unauthorized":          http.StatusUnauthorized,
-			"hasn't been activated": http.StatusForbidden,
-			"this node":             http.StatusNotAcceptable,
+		for _, status := range []struct {
+			keyword string
+			code    int
+		}{
+			{"not found", http.StatusNotFound},
+			{"no such", http.StatusNotFound},
+			{"bad parameter", http.StatusBadRequest},
+			{"no command", http.StatusBadRequest},
+			{"conflict", http.StatusConflict},
+			{"impossible", http.StatusNotAcceptable},
+			{"wrong login/password", http.StatusUnauthorized},
+			{"unauthorized", http.StatusUnauthorized},
+			{"hasn't been activated", http.StatusForbidden},
+			{"this node", http.StatusNotAcceptable},
 		} {
-			if strings.Contains(errStr, keyword) {
-				statusCode = status
+			if strings.Contains(errStr, status.keyword) {
+				statusCode = status.code
 				break
 			}
 		}