diff --git a/Sources/AsyncHTTPClient/HTTPClient.swift b/Sources/AsyncHTTPClient/HTTPClient.swift
index e973b9891..aaad48487 100644
--- a/Sources/AsyncHTTPClient/HTTPClient.swift
+++ b/Sources/AsyncHTTPClient/HTTPClient.swift
@@ -221,73 +221,143 @@ public class HTTPClient {
         }
     }
 
+    /// Specifies redirect processing settings.
+    public typealias RedirectConfiguration = Configuration.RedirectConfiguration
+
     /// Execute `GET` request using specified URL.
     ///
     /// - parameters:
     ///     - url: Remote URL.
-    ///     - deadline: Point in time by which the request must complete.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
     public func get(url: String, deadline: NIODeadline? = nil) -> EventLoopFuture<Response> {
-        return self.get(url: url, deadline: deadline, logger: HTTPClient.loggingDisabled)
+        return self.get(url: url, deadline: deadline, logger: HTTPClient.loggingDisabled, redirects: nil)
+    }
+
+    /// Execute `GET` request using specified URL.
+    ///
+    /// - parameters:
+    ///     - url: Remote URL.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
+    ///     - redirects: Overrides the client's configuration of redirect handling for this request, uses client's configuration if nil.
+    public func get(url: String, deadline: NIODeadline? = nil, redirects: RedirectConfiguration?) -> EventLoopFuture<Response> {
+        return self.get(url: url, deadline: deadline, logger: HTTPClient.loggingDisabled, redirects: redirects)
     }
 
     /// Execute `GET` request using specified URL.
     ///
     /// - parameters:
     ///     - url: Remote URL.
-    ///     - deadline: Point in time by which the request must complete.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
     ///     - logger: The logger to use for this request.
     public func get(url: String, deadline: NIODeadline? = nil, logger: Logger) -> EventLoopFuture<Response> {
-        return self.execute(.GET, url: url, deadline: deadline, logger: logger)
+        return self.get(url: url, deadline: deadline, logger: logger, redirects: nil)
+    }
+
+    /// Execute `GET` request using specified URL.
+    ///
+    /// - parameters:
+    ///     - url: Remote URL.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
+    ///     - logger: The logger to use for this request.
+    ///     - redirects: Overrides the client's configuration of redirect handling for this request, uses client's configuration if nil.
+    public func get(url: String, deadline: NIODeadline? = nil, logger: Logger, redirects: RedirectConfiguration?) -> EventLoopFuture<Response> {
+        return self.execute(.GET, url: url, deadline: deadline, logger: logger, redirects: redirects)
     }
 
     /// Execute `POST` request using specified URL.
     ///
     /// - parameters:
     ///     - url: Remote URL.
-    ///     - body: Request body.
-    ///     - deadline: Point in time by which the request must complete.
+    ///     - body: Request body, the request body is empty if nil.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
     public func post(url: String, body: Body? = nil, deadline: NIODeadline? = nil) -> EventLoopFuture<Response> {
-        return self.post(url: url, body: body, deadline: deadline, logger: HTTPClient.loggingDisabled)
+        return self.post(url: url, body: body, deadline: deadline, logger: HTTPClient.loggingDisabled, redirects: nil)
+    }
+
+    /// Execute `POST` request using specified URL.
+    ///
+    /// - parameters:
+    ///     - url: Remote URL.
+    ///     - body: Request body, the request body is empty if nil.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
+    ///     - redirects: Overrides the client's configuration of redirect handling for this request, uses client's configuration if nil.
+    public func post(url: String, body: Body? = nil, deadline: NIODeadline? = nil, redirects: RedirectConfiguration?) -> EventLoopFuture<Response> {
+        return self.post(url: url, body: body, deadline: deadline, logger: HTTPClient.loggingDisabled, redirects: redirects)
     }
 
     /// Execute `POST` request using specified URL.
     ///
     /// - parameters:
     ///     - url: Remote URL.
-    ///     - body: Request body.
-    ///     - deadline: Point in time by which the request must complete.
+    ///     - body: Request body, the request body is empty if nil.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
     ///     - logger: The logger to use for this request.
     public func post(url: String, body: Body? = nil, deadline: NIODeadline? = nil, logger: Logger) -> EventLoopFuture<Response> {
-        return self.execute(.POST, url: url, body: body, deadline: deadline, logger: logger)
+        return self.post(url: url, body: body, deadline: deadline, logger: logger, redirects: nil)
+    }
+
+    /// Execute `POST` request using specified URL.
+    ///
+    /// - parameters:
+    ///     - url: Remote URL.
+    ///     - body: Request body, the request body is empty if nil.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
+    ///     - logger: The logger to use for this request.
+    ///     - redirects: Overrides the client's configuration of redirect handling for this request, uses client's configuration if nil.
+    public func post(url: String, body: Body? = nil, deadline: NIODeadline? = nil, logger: Logger, redirects: RedirectConfiguration?) -> EventLoopFuture<Response> {
+        return self.execute(.POST, url: url, body: body, deadline: deadline, logger: logger, redirects: redirects)
     }
 
     /// Execute `PATCH` request using specified URL.
     ///
     /// - parameters:
     ///     - url: Remote URL.
-    ///     - body: Request body.
-    ///     - deadline: Point in time by which the request must complete.
+    ///     - body: Request body, the request body is empty if nil.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
     public func patch(url: String, body: Body? = nil, deadline: NIODeadline? = nil) -> EventLoopFuture<Response> {
-        return self.patch(url: url, body: body, deadline: deadline, logger: HTTPClient.loggingDisabled)
+        return self.patch(url: url, body: body, deadline: deadline, logger: HTTPClient.loggingDisabled, redirects: nil)
+    }
+
+    /// Execute `PATCH` request using specified URL.
+    ///
+    /// - parameters:
+    ///     - url: Remote URL.
+    ///     - body: Request body, the request body is empty if nil.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
+    ///     - redirects: Overrides the client's configuration of redirect handling for this request, uses client's configuration if nil.
+    public func patch(url: String, body: Body? = nil, deadline: NIODeadline? = nil, redirects: RedirectConfiguration?) -> EventLoopFuture<Response> {
+        return self.patch(url: url, body: body, deadline: deadline, logger: HTTPClient.loggingDisabled, redirects: redirects)
     }
 
     /// Execute `PATCH` request using specified URL.
     ///
     /// - parameters:
     ///     - url: Remote URL.
-    ///     - body: Request body.
-    ///     - deadline: Point in time by which the request must complete.
+    ///     - body: Request body, the request body is empty if nil.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
     ///     - logger: The logger to use for this request.
     public func patch(url: String, body: Body? = nil, deadline: NIODeadline? = nil, logger: Logger) -> EventLoopFuture<Response> {
-        return self.execute(.PATCH, url: url, body: body, deadline: deadline, logger: logger)
+        return self.patch(url: url, body: body, deadline: deadline, logger: logger, redirects: nil)
+    }
+
+    /// Execute `PATCH` request using specified URL.
+    ///
+    /// - parameters:
+    ///     - url: Remote URL.
+    ///     - body: Request body, the request body is empty if nil.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
+    ///     - logger: The logger to use for this request.
+    ///     - redirects: Overrides the client's configuration of redirect handling for this request, uses client's configuration if nil.
+    public func patch(url: String, body: Body? = nil, deadline: NIODeadline? = nil, logger: Logger, redirects: RedirectConfiguration?) -> EventLoopFuture<Response> {
+        return self.execute(.PATCH, url: url, body: body, deadline: deadline, logger: logger, redirects: redirects)
     }
 
     /// Execute `PUT` request using specified URL.
     ///
     /// - parameters:
     ///     - url: Remote URL.
-    ///     - body: Request body.
-    ///     - deadline: Point in time by which the request must complete.
+    ///     - body: Request body, the request body is empty if nil.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
     public func put(url: String, body: Body? = nil, deadline: NIODeadline? = nil) -> EventLoopFuture<Response> {
         return self.put(url: url, body: body, deadline: deadline, logger: HTTPClient.loggingDisabled)
     }
@@ -296,30 +366,74 @@ public class HTTPClient {
     ///
     /// - parameters:
     ///     - url: Remote URL.
-    ///     - body: Request body.
-    ///     - deadline: Point in time by which the request must complete.
+    ///     - body: Request body, the request body is empty if nil.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
+    ///     - redirects: Overrides the client's configuration of redirect handling for this request, uses client's configuration if nil.
+    public func put(url: String, body: Body? = nil, deadline: NIODeadline? = nil, redirects: RedirectConfiguration?) -> EventLoopFuture<Response> {
+        return self.put(url: url, body: body, deadline: deadline, logger: HTTPClient.loggingDisabled, redirects: redirects)
+    }
+
+    /// Execute `PUT` request using specified URL.
+    ///
+    /// - parameters:
+    ///     - url: Remote URL.
+    ///     - body: Request body, the request body is empty if nil.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
     ///     - logger: The logger to use for this request.
     public func put(url: String, body: Body? = nil, deadline: NIODeadline? = nil, logger: Logger) -> EventLoopFuture<Response> {
-        return self.execute(.PUT, url: url, body: body, deadline: deadline, logger: logger)
+        return self.put(url: url, body: body, deadline: deadline, logger: logger, redirects: nil)
+    }
+
+    /// Execute `PUT` request using specified URL.
+    ///
+    /// - parameters:
+    ///     - url: Remote URL.
+    ///     - body: Request body, the request body is empty if nil.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
+    ///     - logger: The logger to use for this request.
+    ///     - redirects: Overrides the client's configuration of redirect handling for this request, uses client's configuration if nil.
+    public func put(url: String, body: Body? = nil, deadline: NIODeadline? = nil, logger: Logger, redirects: RedirectConfiguration?) -> EventLoopFuture<Response> {
+        return self.execute(.PUT, url: url, body: body, deadline: deadline, logger: logger, redirects: redirects)
     }
 
     /// Execute `DELETE` request using specified URL.
     ///
     /// - parameters:
     ///     - url: Remote URL.
-    ///     - deadline: The time when the request must have been completed by.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
     public func delete(url: String, deadline: NIODeadline? = nil) -> EventLoopFuture<Response> {
-        return self.delete(url: url, deadline: deadline, logger: HTTPClient.loggingDisabled)
+        return self.delete(url: url, deadline: deadline, logger: HTTPClient.loggingDisabled, redirects: nil)
+    }
+
+    /// Execute `DELETE` request using specified URL.
+    ///
+    /// - parameters:
+    ///     - url: Remote URL.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
+    ///     - redirects: Overrides the client's configuration of redirect handling for this request, uses client's configuration if nil.
+    public func delete(url: String, deadline: NIODeadline? = nil, redirects: RedirectConfiguration?) -> EventLoopFuture<Response> {
+        return self.delete(url: url, deadline: deadline, logger: HTTPClient.loggingDisabled, redirects: redirects)
     }
 
     /// Execute `DELETE` request using specified URL.
     ///
     /// - parameters:
     ///     - url: Remote URL.
-    ///     - deadline: The time when the request must have been completed by.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
     ///     - logger: The logger to use for this request.
     public func delete(url: String, deadline: NIODeadline? = nil, logger: Logger) -> EventLoopFuture<Response> {
-        return self.execute(.DELETE, url: url, deadline: deadline, logger: logger)
+        return self.delete(url: url, deadline: deadline, logger: logger, redirects: nil)
+    }
+
+    /// Execute `DELETE` request using specified URL.
+    ///
+    /// - parameters:
+    ///     - url: Remote URL.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
+    ///     - logger: The logger to use for this request.
+    ///     - redirects: Overrides the client's configuration of redirect handling for this request, uses client's configuration if nil.
+    public func delete(url: String, deadline: NIODeadline? = nil, logger: Logger, redirects: RedirectConfiguration?) -> EventLoopFuture<Response> {
+        return self.execute(.DELETE, url: url, deadline: deadline, logger: logger, redirects: redirects)
     }
 
     /// Execute arbitrary HTTP request using specified URL.
@@ -327,13 +441,26 @@ public class HTTPClient {
     /// - parameters:
     ///     - method: Request method.
     ///     - url: Request url.
-    ///     - body: Request body.
-    ///     - deadline: Point in time by which the request must complete.
+    ///     - body: Request body, the request body is empty if nil.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
     ///     - logger: The logger to use for this request.
     public func execute(_ method: HTTPMethod = .GET, url: String, body: Body? = nil, deadline: NIODeadline? = nil, logger: Logger? = nil) -> EventLoopFuture<Response> {
+        return self.execute(method, url: url, body: body, deadline: deadline, logger: logger, redirects: nil)
+    }
+
+    /// Execute arbitrary HTTP request using specified URL.
+    ///
+    /// - parameters:
+    ///     - method: Request method.
+    ///     - url: Request url.
+    ///     - body: Request body, the request body is empty if nil.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
+    ///     - logger: The logger to use for this request, logging is disabled if nil.
+    ///     - redirects: Overrides the client's configuration of redirect handling for this request, uses client's configuration if nil.
+    public func execute(_ method: HTTPMethod = .GET, url: String, body: Body? = nil, deadline: NIODeadline? = nil, logger: Logger? = nil, redirects: RedirectConfiguration?) -> EventLoopFuture<Response> {
         do {
             let request = try Request(url: url, method: method, body: body)
-            return self.execute(request: request, deadline: deadline, logger: logger ?? HTTPClient.loggingDisabled)
+            return self.execute(request: request, deadline: deadline, logger: logger ?? HTTPClient.loggingDisabled, redirects: redirects)
         } catch {
             return self.eventLoopGroup.next().makeFailedFuture(error)
         }
@@ -345,16 +472,30 @@ public class HTTPClient {
     ///     - method: Request method.
     ///     - socketPath: The path to the unix domain socket to connect to.
     ///     - urlPath: The URL path and query that will be sent to the server.
-    ///     - body: Request body.
-    ///     - deadline: Point in time by which the request must complete.
-    ///     - logger: The logger to use for this request.
+    ///     - body: Request body, the request body is empty if nil.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
+    ///     - logger: The logger to use for this request, logging is disabled if nil.
     public func execute(_ method: HTTPMethod = .GET, socketPath: String, urlPath: String, body: Body? = nil, deadline: NIODeadline? = nil, logger: Logger? = nil) -> EventLoopFuture<Response> {
+        return self.execute(method, socketPath: socketPath, urlPath: urlPath, body: body, deadline: deadline, logger: logger, redirects: nil)
+    }
+
+    /// Execute arbitrary HTTP+UNIX request to a unix domain socket path, using the specified URL as the request to send to the server.
+    ///
+    /// - parameters:
+    ///     - method: Request method.
+    ///     - socketPath: The path to the unix domain socket to connect to.
+    ///     - urlPath: The URL path and query that will be sent to the server.
+    ///     - body: Request body, the request body is empty if nil.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
+    ///     - logger: The logger to use for this request, logging is disabled if nil.
+    ///     - redirects: Overrides the client's configuration of redirect handling for this request, uses client's configuration if nil.
+    public func execute(_ method: HTTPMethod = .GET, socketPath: String, urlPath: String, body: Body? = nil, deadline: NIODeadline? = nil, logger: Logger? = nil, redirects: RedirectConfiguration?) -> EventLoopFuture<Response> {
         do {
             guard let url = URL(httpURLWithSocketPath: socketPath, uri: urlPath) else {
                 throw HTTPClientError.invalidURL
             }
             let request = try Request(url: url, method: method, body: body)
-            return self.execute(request: request, deadline: deadline, logger: logger ?? HTTPClient.loggingDisabled)
+            return self.execute(request: request, deadline: deadline, logger: logger ?? HTTPClient.loggingDisabled, redirects: redirects)
         } catch {
             return self.eventLoopGroup.next().makeFailedFuture(error)
         }
@@ -366,16 +507,30 @@ public class HTTPClient {
     ///     - method: Request method.
     ///     - secureSocketPath: The path to the unix domain socket to connect to.
     ///     - urlPath: The URL path and query that will be sent to the server.
-    ///     - body: Request body.
-    ///     - deadline: Point in time by which the request must complete.
-    ///     - logger: The logger to use for this request.
+    ///     - body: Request body, the request body is empty if nil.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
+    ///     - logger: The logger to use for this request, logging is disabled if nil.
     public func execute(_ method: HTTPMethod = .GET, secureSocketPath: String, urlPath: String, body: Body? = nil, deadline: NIODeadline? = nil, logger: Logger? = nil) -> EventLoopFuture<Response> {
+        return self.execute(method, secureSocketPath: secureSocketPath, urlPath: urlPath, body: body, deadline: deadline, logger: logger, redirects: nil)
+    }
+
+    /// Execute arbitrary HTTPS+UNIX request to a unix domain socket path over TLS, using the specified URL as the request to send to the server.
+    ///
+    /// - parameters:
+    ///     - method: Request method.
+    ///     - secureSocketPath: The path to the unix domain socket to connect to.
+    ///     - urlPath: The URL path and query that will be sent to the server.
+    ///     - body: Request body, the request body is empty if nil.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
+    ///     - logger: The logger to use for this request, logging is disabled if nil.
+    ///     - redirects: Overrides the client's configuration of redirect handling for this request, uses client's configuration if nil.
+    public func execute(_ method: HTTPMethod = .GET, secureSocketPath: String, urlPath: String, body: Body? = nil, deadline: NIODeadline? = nil, logger: Logger? = nil, redirects: RedirectConfiguration?) -> EventLoopFuture<Response> {
         do {
             guard let url = URL(httpsURLWithSocketPath: secureSocketPath, uri: urlPath) else {
                 throw HTTPClientError.invalidURL
             }
             let request = try Request(url: url, method: method, body: body)
-            return self.execute(request: request, deadline: deadline, logger: logger ?? HTTPClient.loggingDisabled)
+            return self.execute(request: request, deadline: deadline, logger: logger ?? HTTPClient.loggingDisabled, redirects: redirects)
         } catch {
             return self.eventLoopGroup.next().makeFailedFuture(error)
         }
@@ -385,7 +540,7 @@ public class HTTPClient {
     ///
     /// - parameters:
     ///     - request: HTTP request to execute.
-    ///     - deadline: Point in time by which the request must complete.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
     public func execute(request: Request, deadline: NIODeadline? = nil) -> EventLoopFuture<Response> {
         return self.execute(request: request, deadline: deadline, logger: HTTPClient.loggingDisabled)
     }
@@ -394,19 +549,31 @@ public class HTTPClient {
     ///
     /// - parameters:
     ///     - request: HTTP request to execute.
-    ///     - deadline: Point in time by which the request must complete.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
     ///     - logger: The logger to use for this request.
     public func execute(request: Request, deadline: NIODeadline? = nil, logger: Logger) -> EventLoopFuture<Response> {
         let accumulator = ResponseAccumulator(request: request)
         return self.execute(request: request, delegate: accumulator, deadline: deadline, logger: logger).futureResult
     }
 
+    /// Execute arbitrary HTTP request using specified URL.
+    ///
+    /// - parameters:
+    ///     - request: HTTP request to execute.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
+    ///     - logger: The logger to use for this request.
+    ///     - redirects: Overrides the client's configuration of redirect handling for this request, uses client's configuration if nil.
+    public func execute(request: Request, deadline: NIODeadline? = nil, logger: Logger, redirects: RedirectConfiguration?) -> EventLoopFuture<Response> {
+        let accumulator = ResponseAccumulator(request: request)
+        return self.execute(request: request, delegate: accumulator, deadline: deadline, logger: logger, redirects: redirects).futureResult
+    }
+
     /// Execute arbitrary HTTP request using specified URL.
     ///
     /// - parameters:
     ///     - request: HTTP request to execute.
     ///     - eventLoop: NIO Event Loop preference.
-    ///     - deadline: Point in time by which the request must complete.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
     public func execute(request: Request, eventLoop: EventLoopPreference, deadline: NIODeadline? = nil) -> EventLoopFuture<Response> {
         return self.execute(request: request,
                             eventLoop: eventLoop,
@@ -419,14 +586,34 @@ public class HTTPClient {
     /// - parameters:
     ///     - request: HTTP request to execute.
     ///     - eventLoop: NIO Event Loop preference.
-    ///     - deadline: Point in time by which the request must complete.
-    ///     - logger: The logger to use for this request.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
+    ///     - logger: The logger to use for this request, logging is disabled if nil.
     public func execute(request: Request,
                         eventLoop eventLoopPreference: EventLoopPreference,
                         deadline: NIODeadline? = nil,
                         logger: Logger?) -> EventLoopFuture<Response> {
+        return self.execute(request: request,
+                            eventLoop: eventLoopPreference,
+                            deadline: deadline,
+                            logger: logger,
+                            redirects: nil)
+    }
+
+    /// Execute arbitrary HTTP request and handle response processing using provided delegate.
+    ///
+    /// - parameters:
+    ///     - request: HTTP request to execute.
+    ///     - eventLoop: NIO Event Loop preference.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
+    ///     - logger: The logger to use for this request, logging is disabled if nil.
+    ///     - redirects: Overrides the client's configuration of redirect handling for this request, uses client's configuration if nil.
+    public func execute(request: Request,
+                        eventLoop eventLoopPreference: EventLoopPreference,
+                        deadline: NIODeadline? = nil,
+                        logger: Logger?,
+                        redirects: RedirectConfiguration?) -> EventLoopFuture<Response> {
         let accumulator = ResponseAccumulator(request: request)
-        return self.execute(request: request, delegate: accumulator, eventLoop: eventLoopPreference, deadline: deadline, logger: logger).futureResult
+        return self.execute(request: request, delegate: accumulator, eventLoop: eventLoopPreference, deadline: deadline, logger: logger, redirects: redirects).futureResult
     }
 
     /// Execute arbitrary HTTP request and handle response processing using provided delegate.
@@ -434,7 +621,7 @@ public class HTTPClient {
     /// - parameters:
     ///     - request: HTTP request to execute.
     ///     - delegate: Delegate to process response parts.
-    ///     - deadline: Point in time by which the request must complete.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
     public func execute<Delegate: HTTPClientResponseDelegate>(request: Request,
                                                               delegate: Delegate,
                                                               deadline: NIODeadline? = nil) -> Task<Delegate.Response> {
@@ -446,7 +633,7 @@ public class HTTPClient {
     /// - parameters:
     ///     - request: HTTP request to execute.
     ///     - delegate: Delegate to process response parts.
-    ///     - deadline: Point in time by which the request must complete.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
     ///     - logger: The logger to use for this request.
     public func execute<Delegate: HTTPClientResponseDelegate>(request: Request,
                                                               delegate: Delegate,
@@ -460,9 +647,24 @@ public class HTTPClient {
     /// - parameters:
     ///     - request: HTTP request to execute.
     ///     - delegate: Delegate to process response parts.
-    ///     - eventLoop: NIO Event Loop preference.
-    ///     - deadline: Point in time by which the request must complete.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
     ///     - logger: The logger to use for this request.
+    ///     - redirects: Overrides the client's configuration of redirect handling for this request, uses client's configuration if nil.
+    public func execute<Delegate: HTTPClientResponseDelegate>(request: Request,
+                                                              delegate: Delegate,
+                                                              deadline: NIODeadline? = nil,
+                                                              logger: Logger,
+                                                              redirects: RedirectConfiguration?) -> Task<Delegate.Response> {
+        return self.execute(request: request, delegate: delegate, eventLoop: .indifferent, deadline: deadline, logger: logger, redirects: redirects)
+    }
+
+    /// Execute arbitrary HTTP request and handle response processing using provided delegate.
+    ///
+    /// - parameters:
+    ///     - request: HTTP request to execute.
+    ///     - delegate: Delegate to process response parts.
+    ///     - eventLoop: NIO Event Loop preference.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
     public func execute<Delegate: HTTPClientResponseDelegate>(request: Request,
                                                               delegate: Delegate,
                                                               eventLoop eventLoopPreference: EventLoopPreference,
@@ -480,12 +682,57 @@ public class HTTPClient {
     ///     - request: HTTP request to execute.
     ///     - delegate: Delegate to process response parts.
     ///     - eventLoop: NIO Event Loop preference.
-    ///     - deadline: Point in time by which the request must complete.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
+    ///     - redirects: Overrides the client's configuration of redirect handling for this request, uses client's configuration if nil.
     public func execute<Delegate: HTTPClientResponseDelegate>(request: Request,
                                                               delegate: Delegate,
                                                               eventLoop eventLoopPreference: EventLoopPreference,
                                                               deadline: NIODeadline? = nil,
-                                                              logger originalLogger: Logger?) -> Task<Delegate.Response> {
+                                                              redirects: RedirectConfiguration?) -> Task<Delegate.Response> {
+        return self.execute(request: request,
+                            delegate: delegate,
+                            eventLoop: eventLoopPreference,
+                            deadline: deadline,
+                            logger: HTTPClient.loggingDisabled,
+                            redirects: redirects)
+    }
+
+    /// Execute arbitrary HTTP request and handle response processing using provided delegate.
+    ///
+    /// - parameters:
+    ///     - request: HTTP request to execute.
+    ///     - delegate: Delegate to process response parts.
+    ///     - eventLoop: NIO Event Loop preference.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
+    ///     - logger: The logger to use for this request, logging is disabled if nil.
+    public func execute<Delegate: HTTPClientResponseDelegate>(request: Request,
+                                                              delegate: Delegate,
+                                                              eventLoop eventLoopPreference: EventLoopPreference,
+                                                              deadline: NIODeadline? = nil,
+                                                              logger: Logger?) -> Task<Delegate.Response> {
+        return self.execute(request: request,
+                            delegate: delegate,
+                            eventLoop: eventLoopPreference,
+                            deadline: deadline,
+                            logger: logger,
+                            redirects: nil)
+    }
+
+    /// Execute arbitrary HTTP request and handle response processing using provided delegate.
+    ///
+    /// - parameters:
+    ///     - request: HTTP request to execute.
+    ///     - delegate: Delegate to process response parts.
+    ///     - eventLoop: NIO Event Loop preference.
+    ///     - deadline: Point in time by which the request must complete, determined by the library if nil.
+    ///     - logger: The logger to use for this request, logging is disabled if nil.
+    ///     - redirects: Overrides the client's configuration of redirect handling for this request, uses client's configuration if nil.
+    public func execute<Delegate: HTTPClientResponseDelegate>(request: Request,
+                                                              delegate: Delegate,
+                                                              eventLoop eventLoopPreference: EventLoopPreference,
+                                                              deadline: NIODeadline? = nil,
+                                                              logger originalLogger: Logger?,
+                                                              redirects: RedirectConfiguration?) -> Task<Delegate.Response> {
         let logger = (originalLogger ?? HTTPClient.loggingDisabled).attachingRequestInformation(request, requestID: globalRequestID.add(1))
         let taskEL: EventLoop
         switch eventLoopPreference.preference {
@@ -521,7 +768,9 @@ public class HTTPClient {
         }
 
         let redirectHandler: RedirectHandler<Delegate.Response>?
-        switch self.configuration.redirectConfiguration.configuration {
+        let prevailingConfiguration = redirects?.configuration ?? self.configuration.redirectConfiguration.configuration
+
+        switch prevailingConfiguration {
         case .follow(let max, let allowCycles):
             var request = request
             if request.redirectState == nil {
@@ -531,7 +780,8 @@ public class HTTPClient {
                 self.execute(request: newRequest,
                              delegate: delegate,
                              eventLoop: eventLoopPreference,
-                             deadline: deadline)
+                             deadline: deadline,
+                             redirects: .follow(max: max, allowCycles: allowCycles))
             }
         case .disallow:
             redirectHandler = nil
diff --git a/Tests/AsyncHTTPClientTests/HTTPClientTests+XCTest.swift b/Tests/AsyncHTTPClientTests/HTTPClientTests+XCTest.swift
index 4a5acc298..71a84bddf 100644
--- a/Tests/AsyncHTTPClientTests/HTTPClientTests+XCTest.swift
+++ b/Tests/AsyncHTTPClientTests/HTTPClientTests+XCTest.swift
@@ -68,7 +68,10 @@ extension HTTPClientTests {
             ("testDecompression", testDecompression),
             ("testDecompressionLimit", testDecompressionLimit),
             ("testLoopDetectionRedirectLimit", testLoopDetectionRedirectLimit),
+            ("testLoopDetectionRedirectLimitPerRequest", testLoopDetectionRedirectLimitPerRequest),
             ("testCountRedirectLimit", testCountRedirectLimit),
+            ("testCountRedirectLimitPerRequest", testCountRedirectLimitPerRequest),
+            ("testNoRedirectPerRequest", testNoRedirectPerRequest),
             ("testMultipleConcurrentRequests", testMultipleConcurrentRequests),
             ("testWorksWith500Error", testWorksWith500Error),
             ("testWorksWithHTTP10Response", testWorksWithHTTP10Response),
diff --git a/Tests/AsyncHTTPClientTests/HTTPClientTests.swift b/Tests/AsyncHTTPClientTests/HTTPClientTests.swift
index 6d611a679..ed94b853d 100644
--- a/Tests/AsyncHTTPClientTests/HTTPClientTests.swift
+++ b/Tests/AsyncHTTPClientTests/HTTPClientTests.swift
@@ -929,6 +929,21 @@ class HTTPClientTests: XCTestCase {
         }
     }
 
+    func testLoopDetectionRedirectLimitPerRequest() throws {
+        let localHTTPBin = HTTPBin(ssl: true)
+        let localClient = HTTPClient(eventLoopGroupProvider: .shared(self.clientGroup),
+                                     configuration: HTTPClient.Configuration(certificateVerification: .none, redirectConfiguration: .follow(max: 5, allowCycles: true)))
+
+        defer {
+            XCTAssertNoThrow(try localClient.syncShutdown())
+            XCTAssertNoThrow(try localHTTPBin.shutdown())
+        }
+
+        XCTAssertThrowsError(try localClient.get(url: "https://localhost:\(localHTTPBin.port)/redirect/infinite1", redirects: .follow(max: 5, allowCycles: false)).wait(), "Should fail with redirect limit") { error in
+            XCTAssertEqual(error as? HTTPClientError, HTTPClientError.redirectCycleDetected)
+        }
+    }
+
     func testCountRedirectLimit() throws {
         let localHTTPBin = HTTPBin(ssl: true)
         let localClient = HTTPClient(eventLoopGroupProvider: .shared(self.clientGroup),
@@ -944,6 +959,34 @@ class HTTPClientTests: XCTestCase {
         }
     }
 
+    func testCountRedirectLimitPerRequest() throws {
+        let localHTTPBin = HTTPBin(ssl: true)
+        let localClient = HTTPClient(eventLoopGroupProvider: .shared(self.clientGroup),
+                                     configuration: HTTPClient.Configuration(certificateVerification: .none, redirectConfiguration: .disallow))
+
+        defer {
+            XCTAssertNoThrow(try localClient.syncShutdown())
+            XCTAssertNoThrow(try localHTTPBin.shutdown())
+        }
+
+        XCTAssertThrowsError(try localClient.get(url: "https://localhost:\(localHTTPBin.port)/redirect/infinite1", redirects: .follow(max: 5, allowCycles: true)).wait(), "Should fail with redirect limit") { error in
+            XCTAssertEqual(error as? HTTPClientError, HTTPClientError.redirectLimitReached)
+        }
+    }
+
+    func testNoRedirectPerRequest() throws {
+        let localHTTPBin = HTTPBin(ssl: true)
+        let localClient = HTTPClient(eventLoopGroupProvider: .shared(self.clientGroup),
+                                     configuration: HTTPClient.Configuration(certificateVerification: .none, redirectConfiguration: .follow(max: 5, allowCycles: true)))
+
+        defer {
+            XCTAssertNoThrow(try localClient.syncShutdown())
+            XCTAssertNoThrow(try localHTTPBin.shutdown())
+        }
+
+        XCTAssertNoThrow(try localClient.get(url: "https://localhost:\(localHTTPBin.port)/redirect/infinite1", redirects: .disallow).wait())
+    }
+
     func testMultipleConcurrentRequests() throws {
         let numberOfRequestsPerThread = 1000
         let numberOfParallelWorkers = 5