Browse code

client: Client.doRequest: use early return

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Sebastiaan van Stijn authored on 2025/06/26 21:14:50
Showing 2 changed files
... ...
@@ -135,66 +135,66 @@ func (cli *Client) sendRequest(ctx context.Context, method, path string, query u
135 135
 
136 136
 func (cli *Client) doRequest(req *http.Request) (*http.Response, error) {
137 137
 	resp, err := cli.client.Do(req)
138
-	if err != nil {
139
-		if cli.scheme != "https" && strings.Contains(err.Error(), "malformed HTTP response") {
140
-			return nil, errConnectionFailed{fmt.Errorf("%v.\n* Are you trying to connect to a TLS-enabled daemon without TLS?", err)}
141
-		}
138
+	if err == nil {
139
+		return resp, nil
140
+	}
142 141
 
143
-		if cli.scheme == "https" && strings.Contains(err.Error(), "bad certificate") {
144
-			return nil, errConnectionFailed{errors.Wrap(err, "the server probably has client authentication (--tlsverify) enabled; check your TLS client certification settings")}
145
-		}
142
+	if cli.scheme != "https" && strings.Contains(err.Error(), "malformed HTTP response") {
143
+		return nil, errConnectionFailed{fmt.Errorf("%v.\n* Are you trying to connect to a TLS-enabled daemon without TLS?", err)}
144
+	}
146 145
 
147
-		// Don't decorate context sentinel errors; users may be comparing to
148
-		// them directly.
149
-		if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
150
-			return nil, err
151
-		}
146
+	if cli.scheme == "https" && strings.Contains(err.Error(), "bad certificate") {
147
+		return nil, errConnectionFailed{errors.Wrap(err, "the server probably has client authentication (--tlsverify) enabled; check your TLS client certification settings")}
148
+	}
152 149
 
153
-		var uErr *url.Error
154
-		if errors.As(err, &uErr) {
155
-			var nErr *net.OpError
156
-			if errors.As(uErr.Err, &nErr) {
157
-				if os.IsPermission(nErr.Err) {
158
-					return nil, errConnectionFailed{errors.Wrapf(err, "permission denied while trying to connect to the Docker daemon socket at %v", cli.host)}
159
-				}
160
-			}
161
-		}
150
+	// Don't decorate context sentinel errors; users may be comparing to
151
+	// them directly.
152
+	if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
153
+		return nil, err
154
+	}
162 155
 
163
-		var nErr net.Error
164
-		if errors.As(err, &nErr) {
165
-			// FIXME(thaJeztah): any net.Error should be considered a connection error (but we should include the original error)?
166
-			if nErr.Timeout() {
167
-				return nil, connectionFailed(cli.host)
168
-			}
169
-			if strings.Contains(nErr.Error(), "connection refused") || strings.Contains(nErr.Error(), "dial unix") {
170
-				return nil, connectionFailed(cli.host)
156
+	var uErr *url.Error
157
+	if errors.As(err, &uErr) {
158
+		var nErr *net.OpError
159
+		if errors.As(uErr.Err, &nErr) {
160
+			if os.IsPermission(nErr.Err) {
161
+				return nil, errConnectionFailed{errors.Wrapf(err, "permission denied while trying to connect to the Docker daemon socket at %v", cli.host)}
171 162
 			}
172 163
 		}
164
+	}
173 165
 
174
-		// Although there's not a strongly typed error for this in go-winio,
175
-		// lots of people are using the default configuration for the docker
176
-		// daemon on Windows where the daemon is listening on a named pipe
177
-		// `//./pipe/docker_engine, and the client must be running elevated.
178
-		// Give users a clue rather than the not-overly useful message
179
-		// such as `error during connect: Get http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.26/info:
180
-		// open //./pipe/docker_engine: The system cannot find the file specified.`.
181
-		// Note we can't string compare "The system cannot find the file specified" as
182
-		// this is localised - for example in French the error would be
183
-		// `open //./pipe/docker_engine: Le fichier spécifié est introuvable.`
184
-		if strings.Contains(err.Error(), `open //./pipe/docker_engine`) {
185
-			// Checks if client is running with elevated privileges
186
-			if f, elevatedErr := os.Open(`\\.\PHYSICALDRIVE0`); elevatedErr != nil {
187
-				err = errors.Wrap(err, "in the default daemon configuration on Windows, the docker client must be run with elevated privileges to connect")
188
-			} else {
189
-				_ = f.Close()
190
-				err = errors.Wrap(err, "this error may indicate that the docker daemon is not running")
191
-			}
166
+	var nErr net.Error
167
+	if errors.As(err, &nErr) {
168
+		// FIXME(thaJeztah): any net.Error should be considered a connection error (but we should include the original error)?
169
+		if nErr.Timeout() {
170
+			return nil, connectionFailed(cli.host)
192 171
 		}
172
+		if strings.Contains(nErr.Error(), "connection refused") || strings.Contains(nErr.Error(), "dial unix") {
173
+			return nil, connectionFailed(cli.host)
174
+		}
175
+	}
193 176
 
194
-		return nil, errConnectionFailed{errors.Wrap(err, "error during connect")}
177
+	// Although there's not a strongly typed error for this in go-winio,
178
+	// lots of people are using the default configuration for the docker
179
+	// daemon on Windows where the daemon is listening on a named pipe
180
+	// `//./pipe/docker_engine, and the client must be running elevated.
181
+	// Give users a clue rather than the not-overly useful message
182
+	// such as `error during connect: Get http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.26/info:
183
+	// open //./pipe/docker_engine: The system cannot find the file specified.`.
184
+	// Note we can't string compare "The system cannot find the file specified" as
185
+	// this is localised - for example in French the error would be
186
+	// `open //./pipe/docker_engine: Le fichier spécifié est introuvable.`
187
+	if strings.Contains(err.Error(), `open //./pipe/docker_engine`) {
188
+		// Checks if client is running with elevated privileges
189
+		if f, elevatedErr := os.Open(`\\.\PHYSICALDRIVE0`); elevatedErr != nil {
190
+			err = errors.Wrap(err, "in the default daemon configuration on Windows, the docker client must be run with elevated privileges to connect")
191
+		} else {
192
+			_ = f.Close()
193
+			err = errors.Wrap(err, "this error may indicate that the docker daemon is not running")
194
+		}
195 195
 	}
196 196
 
197
-	return resp, nil
197
+	return nil, errConnectionFailed{errors.Wrap(err, "error during connect")}
198 198
 }
199 199
 
200 200
 func (cli *Client) checkResponseErr(serverResp *http.Response) (retErr error) {
... ...
@@ -135,66 +135,66 @@ func (cli *Client) sendRequest(ctx context.Context, method, path string, query u
135 135
 
136 136
 func (cli *Client) doRequest(req *http.Request) (*http.Response, error) {
137 137
 	resp, err := cli.client.Do(req)
138
-	if err != nil {
139
-		if cli.scheme != "https" && strings.Contains(err.Error(), "malformed HTTP response") {
140
-			return nil, errConnectionFailed{fmt.Errorf("%v.\n* Are you trying to connect to a TLS-enabled daemon without TLS?", err)}
141
-		}
138
+	if err == nil {
139
+		return resp, nil
140
+	}
142 141
 
143
-		if cli.scheme == "https" && strings.Contains(err.Error(), "bad certificate") {
144
-			return nil, errConnectionFailed{errors.Wrap(err, "the server probably has client authentication (--tlsverify) enabled; check your TLS client certification settings")}
145
-		}
142
+	if cli.scheme != "https" && strings.Contains(err.Error(), "malformed HTTP response") {
143
+		return nil, errConnectionFailed{fmt.Errorf("%v.\n* Are you trying to connect to a TLS-enabled daemon without TLS?", err)}
144
+	}
146 145
 
147
-		// Don't decorate context sentinel errors; users may be comparing to
148
-		// them directly.
149
-		if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
150
-			return nil, err
151
-		}
146
+	if cli.scheme == "https" && strings.Contains(err.Error(), "bad certificate") {
147
+		return nil, errConnectionFailed{errors.Wrap(err, "the server probably has client authentication (--tlsverify) enabled; check your TLS client certification settings")}
148
+	}
152 149
 
153
-		var uErr *url.Error
154
-		if errors.As(err, &uErr) {
155
-			var nErr *net.OpError
156
-			if errors.As(uErr.Err, &nErr) {
157
-				if os.IsPermission(nErr.Err) {
158
-					return nil, errConnectionFailed{errors.Wrapf(err, "permission denied while trying to connect to the Docker daemon socket at %v", cli.host)}
159
-				}
160
-			}
161
-		}
150
+	// Don't decorate context sentinel errors; users may be comparing to
151
+	// them directly.
152
+	if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
153
+		return nil, err
154
+	}
162 155
 
163
-		var nErr net.Error
164
-		if errors.As(err, &nErr) {
165
-			// FIXME(thaJeztah): any net.Error should be considered a connection error (but we should include the original error)?
166
-			if nErr.Timeout() {
167
-				return nil, connectionFailed(cli.host)
168
-			}
169
-			if strings.Contains(nErr.Error(), "connection refused") || strings.Contains(nErr.Error(), "dial unix") {
170
-				return nil, connectionFailed(cli.host)
156
+	var uErr *url.Error
157
+	if errors.As(err, &uErr) {
158
+		var nErr *net.OpError
159
+		if errors.As(uErr.Err, &nErr) {
160
+			if os.IsPermission(nErr.Err) {
161
+				return nil, errConnectionFailed{errors.Wrapf(err, "permission denied while trying to connect to the Docker daemon socket at %v", cli.host)}
171 162
 			}
172 163
 		}
164
+	}
173 165
 
174
-		// Although there's not a strongly typed error for this in go-winio,
175
-		// lots of people are using the default configuration for the docker
176
-		// daemon on Windows where the daemon is listening on a named pipe
177
-		// `//./pipe/docker_engine, and the client must be running elevated.
178
-		// Give users a clue rather than the not-overly useful message
179
-		// such as `error during connect: Get http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.26/info:
180
-		// open //./pipe/docker_engine: The system cannot find the file specified.`.
181
-		// Note we can't string compare "The system cannot find the file specified" as
182
-		// this is localised - for example in French the error would be
183
-		// `open //./pipe/docker_engine: Le fichier spécifié est introuvable.`
184
-		if strings.Contains(err.Error(), `open //./pipe/docker_engine`) {
185
-			// Checks if client is running with elevated privileges
186
-			if f, elevatedErr := os.Open(`\\.\PHYSICALDRIVE0`); elevatedErr != nil {
187
-				err = errors.Wrap(err, "in the default daemon configuration on Windows, the docker client must be run with elevated privileges to connect")
188
-			} else {
189
-				_ = f.Close()
190
-				err = errors.Wrap(err, "this error may indicate that the docker daemon is not running")
191
-			}
166
+	var nErr net.Error
167
+	if errors.As(err, &nErr) {
168
+		// FIXME(thaJeztah): any net.Error should be considered a connection error (but we should include the original error)?
169
+		if nErr.Timeout() {
170
+			return nil, connectionFailed(cli.host)
192 171
 		}
172
+		if strings.Contains(nErr.Error(), "connection refused") || strings.Contains(nErr.Error(), "dial unix") {
173
+			return nil, connectionFailed(cli.host)
174
+		}
175
+	}
193 176
 
194
-		return nil, errConnectionFailed{errors.Wrap(err, "error during connect")}
177
+	// Although there's not a strongly typed error for this in go-winio,
178
+	// lots of people are using the default configuration for the docker
179
+	// daemon on Windows where the daemon is listening on a named pipe
180
+	// `//./pipe/docker_engine, and the client must be running elevated.
181
+	// Give users a clue rather than the not-overly useful message
182
+	// such as `error during connect: Get http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.26/info:
183
+	// open //./pipe/docker_engine: The system cannot find the file specified.`.
184
+	// Note we can't string compare "The system cannot find the file specified" as
185
+	// this is localised - for example in French the error would be
186
+	// `open //./pipe/docker_engine: Le fichier spécifié est introuvable.`
187
+	if strings.Contains(err.Error(), `open //./pipe/docker_engine`) {
188
+		// Checks if client is running with elevated privileges
189
+		if f, elevatedErr := os.Open(`\\.\PHYSICALDRIVE0`); elevatedErr != nil {
190
+			err = errors.Wrap(err, "in the default daemon configuration on Windows, the docker client must be run with elevated privileges to connect")
191
+		} else {
192
+			_ = f.Close()
193
+			err = errors.Wrap(err, "this error may indicate that the docker daemon is not running")
194
+		}
195 195
 	}
196 196
 
197
-	return resp, nil
197
+	return nil, errConnectionFailed{errors.Wrap(err, "error during connect")}
198 198
 }
199 199
 
200 200
 func (cli *Client) checkResponseErr(serverResp *http.Response) (retErr error) {