swift-server / swift-server/async-http-client

for debugging purposes, we should offer an option to switch on plain text .pcap recording

Open
#239 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

good first issue kind/enhancement 🆕 semver/minor
Dominant language
Swift
Stars
1.1k
Forks
156
PR merge metrics
No merged PRs in 30d

Description

for debugging purposes, we should offer an option to switch on plain text .pcap recording.

It should be very clear that it's for debugging because NIOWritePCAPHandler.SynchronisedFileSink blocks the event loop (we could write an async file sink ofc)...

A pretty terrible patch that can serve as example (but not the final impl ofc) is here:

diff --git a/Package.swift b/Package.swift
index bce6b69..0575c2d 100644
--- a/Package.swift
+++ b/Package.swift
@@ -31,7 +31,7 @@ let package = Package(
         .target(
             name: "AsyncHTTPClient",
             dependencies: ["NIO", "NIOHTTP1", "NIOSSL", "NIOConcurrencyHelpers", "NIOHTTPCompression",
-                           "NIOFoundationCompat", "NIOTransportServices", "Logging"]
+                           "NIOFoundationCompat", "NIOTransportServices", "Logging", "NIOExtras"]
         ),
         .testTarget(
             name: "AsyncHTTPClientTests",
diff --git a/Sources/AsyncHTTPClient/ConnectionPool.swift b/Sources/AsyncHTTPClient/ConnectionPool.swift
index 46e0b61..03abfc3 100644
--- a/Sources/AsyncHTTPClient/ConnectionPool.swift
+++ b/Sources/AsyncHTTPClient/ConnectionPool.swift
@@ -20,6 +20,7 @@ import NIOHTTP1
 import NIOHTTPCompression
 import NIOTLS
 import NIOTransportServices
+import NIOExtras
 
 /// A connection pool that manages and creates new connections to hosts respecting the specified preferences
 ///
@@ -257,6 +258,10 @@ struct ConnectionKey: Hashable {
     }
 }
 
+let fileSink = try? NIOWritePCAPHandler.SynchronizedFileSink.fileSinkWritingToFile(path: "/tmp/ahc-\(getpid()).pcap") { error in
+    print("AHC ERROR: something went wrong creating the file sink: \(error)")
+}
+
 /// A connection provider of `HTTP/1.1` connections with a given `Key` (host, scheme, port)
 ///
 /// On top of enabling connection reuse this provider it also facilitates the creation
@@ -529,9 +534,22 @@ class HTTP1ConnectionProvider {
             let requiresSSLHandler = self.configuration.proxy != nil && self.key.scheme.requiresTLS
             let handshakePromise = channel.eventLoop.makePromise(of: Void.self)
 
+
             channel.pipeline.addSSLHandlerIfNeeded(for: self.key, tlsConfiguration: self.configuration.tlsConfiguration, addSSLClient: requiresSSLHandler, handshakePromise: handshakePromise)
 
+            func addWritePCAP() -> EventLoopFuture<Void> {
+                if let fileSink = fileSink {
+                    return channel.pipeline.addHandler(NIOWritePCAPHandler(mode: .client, fileSink: fileSink.write(buffer:)),
+                                                position: .last)
+                } else {
+                    return channel.eventLoop.makeSucceededFuture(())
+                }
+
+            }
+
             return handshakePromise.futureResult.flatMap {
+                addWritePCAP()
+            }.flatMap {
                 channel.pipeline.addHTTPClientHandlers(leftOverBytesStrategy: .forwardBytes)
             }.flatMap {
                 #if canImport(Network)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with Package.swift and Sources/AsyncHTTPClient/ConnectionPool.swift, especially HTTP1ConnectionProvider and the pipeline setup around NIOWritePCAPHandler.SynchronizedFileSink. Trace how connection configuration reaches that entry point and define an explicit debugging-only option. Done means callers can enable plain-text .pcap recording without enabling it by default, with the blocking behavior clearly documented.

Written by the indexing model from the issue text.

Assessment

Tech stack
swift
Domain
networking
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.