@@ -2,6 +2,7 @@ import Foundation
22#if canImport(FoundationNetworking)
33import FoundationNetworking
44#endif
5+ import HTTPTypes
56
67/// The components to be logged.
78public struct LoggingComponents : OptionSet {
@@ -17,8 +18,8 @@ public struct LoggingComponents: OptionSet {
1718 public static let query = LoggingComponents ( rawValue: 1 << 8 )
1819 public static let uuid = LoggingComponents ( rawValue: 1 << 9 )
1920 public static let location = LoggingComponents ( rawValue: 1 << 10 )
20- public static let onRequest = LoggingComponents ( rawValue: 1 << 11 )
21- public static let cURL = LoggingComponents ( rawValue: 1 << 12 )
21+ public static let onRequest = LoggingComponents ( rawValue: 1 << 11 )
22+ public static let cURL = LoggingComponents ( rawValue: 1 << 12 )
2223
2324 public static var url : LoggingComponents { [ . path, . baseURL, . query] }
2425
@@ -71,6 +72,7 @@ public extension LoggingComponents {
7172 func requestMessage(
7273 for request: HTTPRequestComponents ,
7374 uuid: UUID ,
75+ maskedHeaders: Set < HTTPField . Name > ,
7476 fileIDLine: FileIDLine ?
7577 ) -> String {
7678 guard !isEmpty else { return " " }
@@ -92,7 +94,7 @@ public extension LoggingComponents {
9294 message += " ( \( body. count) -byte body) "
9395 }
9496 if contains ( . headers) , !request. headers. isEmpty {
95- message += " \n \( request. headers. multilineDescription) "
97+ message += " \n \( request. headers. multilineDescription ( masked : maskedHeaders ) ) "
9698 isMultiline = true
9799 }
98100 if contains ( . body) , let body = request. body? . data, let bodyString = String ( data: body, encoding: . utf8) {
@@ -104,7 +106,7 @@ public extension LoggingComponents {
104106 isMultiline = true
105107 }
106108 if contains ( . cURL) {
107- message += " \n \( request. cURL) "
109+ message += " \n \( request. cURL ( maskedHeaders : maskedHeaders ) ) "
108110 isMultiline = true
109111 }
110112 if isMultiline {
@@ -123,7 +125,8 @@ public extension LoggingComponents {
123125 data: Data ? ,
124126 duration: TimeInterval ,
125127 error: Error ? = nil ,
126- fileIDLine: FileIDLine ?
128+ maskedHeaders: Set < HTTPField . Name > ,
129+ fileIDLine: FileIDLine ?
127130 ) -> String {
128131 responseMessage (
129132 uuid: uuid,
@@ -133,7 +136,8 @@ public extension LoggingComponents {
133136 headers: response. headerFields,
134137 duration: duration,
135138 error: error,
136- fileIDLine: fileIDLine
139+ maskedHeaders: maskedHeaders,
140+ fileIDLine: fileIDLine
137141 )
138142 }
139143
@@ -145,17 +149,18 @@ public extension LoggingComponents {
145149 headers: HTTPFields = [ : ] ,
146150 duration: TimeInterval ? = nil ,
147151 error: Error ? = nil ,
148- fileIDLine: FileIDLine ?
152+ maskedHeaders: Set < HTTPField . Name > ,
153+ fileIDLine: FileIDLine ?
149154 ) -> String {
150155 guard !isEmpty else { return " " }
151- var message = " <-- "
152- if let request {
153- message = requestMessage ( for: request, uuid: uuid, fileIDLine: fileIDLine) + " \n " + message
154- } else {
155- if contains ( . uuid) {
156- message = " [ \( uuid. uuidString) ] \n " + message
157- }
158- }
156+ var message = " <-- "
157+ if let request {
158+ message = requestMessage ( for: request, uuid: uuid, maskedHeaders : maskedHeaders , fileIDLine: fileIDLine) + " \n " + message
159+ } else {
160+ if contains ( . uuid) {
161+ message = " [ \( uuid. uuidString) ] \n " + message
162+ }
163+ }
159164 switch ( statusCode? . kind, error) {
160165 case ( _, . some) , ( . serverError, _) , ( . clientError, _) , ( . invalid, _) :
161166 message. append ( " 🛑 " )
@@ -187,7 +192,7 @@ public extension LoggingComponents {
187192 }
188193
189194 if contains ( . headers) , !headers. isEmpty {
190- message += " \n \( headers. multilineDescription) "
195+ message += " \n \( headers. multilineDescription ( masked : maskedHeaders ) ) "
191196 isMultiline = true
192197 }
193198 if contains ( . body) , let body = data, let bodyString = String ( data: body, encoding: . utf8) {
@@ -207,6 +212,7 @@ public extension LoggingComponents {
207212 error: Error ,
208213 request: HTTPRequestComponents ? = nil ,
209214 duration: TimeInterval ? = nil ,
215+ maskedHeaders: Set < HTTPField . Name > ,
210216 fileIDLine: FileIDLine ? = nil
211217 ) -> String {
212218 var message = contains ( . uuid) && request == nil ? " [ \( uuid. uuidString) ] " : " "
@@ -215,8 +221,8 @@ public extension LoggingComponents {
215221 }
216222
217223 if let request {
218- message = requestMessage ( for: request, uuid: uuid, fileIDLine: fileIDLine) + " \n " + message
219- } else if let fileIDLine, contains ( . location) {
224+ message = requestMessage ( for: request, uuid: uuid, maskedHeaders : maskedHeaders , fileIDLine: fileIDLine) + " \n " + message
225+ } else if let fileIDLine, contains ( . location) {
220226 message = " \( fileIDLine. fileID) / \( fileIDLine. line) \n " + message
221227 }
222228 message += " ❗️ \( error. humanReadable) ❗️ "
@@ -248,7 +254,10 @@ public extension LoggingComponents {
248254
249255private extension HTTPFields {
250256
251- var multilineDescription : String {
252- map { " \( $0. name) : \( $0. value) " } . joined ( separator: " \n " )
257+ func multilineDescription( masked: Set < HTTPField . Name > ) -> String {
258+ map {
259+ " \( $0. name) : \( masked. contains ( $0. name) ? " *** " : $0. value) "
260+ }
261+ . joined ( separator: " \n " )
253262 }
254263}
0 commit comments