-
Notifications
You must be signed in to change notification settings - Fork 125
Add Request/Response History to all public Response
types
#817
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
dc1b10e
80cdab5
a244717
e9577c5
b35e140
747e3b8
c297779
54bb5d0
2ee71ce
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,17 +13,22 @@ | |
//===----------------------------------------------------------------------===// | ||
|
||
import Algorithms | ||
import Foundation | ||
import Logging | ||
import NIOConcurrencyHelpers | ||
import NIOCore | ||
import NIOHTTP1 | ||
import NIOPosix | ||
import NIOSSL | ||
|
||
#if compiler(>=6.0) | ||
import Foundation | ||
#else | ||
@preconcurrency import Foundation | ||
#endif | ||
|
||
extension HTTPClient { | ||
/// A request body. | ||
public struct Body { | ||
public struct Body: Sendable { | ||
/// A streaming uploader. | ||
/// | ||
/// ``StreamWriter`` abstracts | ||
|
@@ -209,7 +214,7 @@ extension HTTPClient { | |
} | ||
|
||
/// Represents an HTTP request. | ||
public struct Request { | ||
public struct Request: Sendable { | ||
/// Request HTTP method, defaults to `GET`. | ||
public let method: HTTPMethod | ||
/// Remote URL. | ||
|
@@ -377,6 +382,13 @@ extension HTTPClient { | |
public var headers: HTTPHeaders | ||
/// Response body. | ||
public var body: ByteBuffer? | ||
/// The history of all requests and responses in redirect order. | ||
public var history: [RequestResponse] | ||
|
||
/// The target URL (after redirects) of the response. | ||
public var url: URL? { | ||
self.history.last?.request.url | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we think There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. as mentioned above, but copying here: Not from any |
||
} | ||
|
||
/// Create HTTP `Response`. | ||
/// | ||
|
@@ -392,6 +404,7 @@ extension HTTPClient { | |
self.version = HTTPVersion(major: 1, minor: 1) | ||
self.headers = headers | ||
self.body = body | ||
self.history = [] | ||
} | ||
|
||
/// Create HTTP `Response`. | ||
|
@@ -414,6 +427,32 @@ extension HTTPClient { | |
self.version = version | ||
self.headers = headers | ||
self.body = body | ||
self.history = [] | ||
} | ||
|
||
/// Create HTTP `Response`. | ||
/// | ||
/// - parameters: | ||
/// - host: Remote host of the request. | ||
/// - status: Response HTTP status. | ||
/// - version: Response HTTP version. | ||
/// - headers: Reponse HTTP headers. | ||
/// - body: Response body. | ||
/// - history: History of all requests and responses in redirect order. | ||
public init( | ||
host: String, | ||
status: HTTPResponseStatus, | ||
version: HTTPVersion, | ||
headers: HTTPHeaders, | ||
body: ByteBuffer?, | ||
history: [RequestResponse] | ||
) { | ||
self.host = host | ||
self.status = status | ||
self.version = version | ||
self.headers = headers | ||
self.body = body | ||
self.history = history | ||
} | ||
} | ||
|
||
|
@@ -457,6 +496,16 @@ extension HTTPClient { | |
} | ||
} | ||
} | ||
|
||
public struct RequestResponse: Sendable { | ||
public var request: Request | ||
public var responseHead: HTTPResponseHead | ||
|
||
public init(request: Request, responseHead: HTTPResponseHead) { | ||
self.request = request | ||
self.responseHead = responseHead | ||
} | ||
} | ||
} | ||
|
||
/// The default ``HTTPClientResponseDelegate``. | ||
|
@@ -485,6 +534,7 @@ public final class ResponseAccumulator: HTTPClientResponseDelegate { | |
} | ||
} | ||
|
||
var history = [HTTPClient.RequestResponse]() | ||
var state = State.idle | ||
let requestMethod: HTTPMethod | ||
let requestHost: String | ||
|
@@ -521,6 +571,14 @@ public final class ResponseAccumulator: HTTPClientResponseDelegate { | |
self.maxBodySize = maxBodySize | ||
} | ||
|
||
public func didVisitURL( | ||
task: HTTPClient.Task<HTTPClient.Response>, | ||
_ request: HTTPClient.Request, | ||
_ head: HTTPResponseHead | ||
) { | ||
self.history.append(.init(request: request, responseHead: head)) | ||
} | ||
|
||
public func didReceiveHead(task: HTTPClient.Task<Response>, _ head: HTTPResponseHead) -> EventLoopFuture<Void> { | ||
switch self.state { | ||
case .idle: | ||
|
@@ -596,15 +654,17 @@ public final class ResponseAccumulator: HTTPClientResponseDelegate { | |
status: head.status, | ||
version: head.version, | ||
headers: head.headers, | ||
body: nil | ||
body: nil, | ||
history: self.history | ||
) | ||
case .body(let head, let body): | ||
return Response( | ||
host: self.requestHost, | ||
status: head.status, | ||
version: head.version, | ||
headers: head.headers, | ||
body: body | ||
body: body, | ||
history: self.history | ||
) | ||
case .end: | ||
preconditionFailure("request already processed") | ||
|
Uh oh!
There was an error while loading. Please reload this page.