@@ -55,4 +55,172 @@ final class BugsnagTests: XCTestCase {
5555 let request = Request ( using: application)
5656 try reporter. report ( NotFound ( ) , on: request) . wait ( )
5757 }
58+
59+ func testKeyFiltersWorkInRequestBody( ) throws {
60+ var capturedSendReportParameters : (
61+ host: String ,
62+ headers: HTTPHeaders ,
63+ body: Data ,
64+ container: Container
65+ ) ?
66+
67+ let reporter = BugsnagReporter (
68+ config: . init( apiKey: " apiKey " , releaseStage: " test " , keyFilters: [ " password " , " email " ] ) ,
69+ sendReport: { host, headers, data, container in
70+ capturedSendReportParameters = ( host, headers, data, container)
71+ return container. future ( Response ( http: HTTPResponse ( status: . ok) , using: container) )
72+ } )
73+ let application = try Application . test ( )
74+ let request = Request ( using: application)
75+ request. http. method = . POST
76+ request. http. body = TestBody . default. httpBody
77+
78+ _ = try ! reporter. report ( NotFound ( ) , on: request) . wait ( )
79+
80+ guard let params = capturedSendReportParameters else {
81+ XCTFail ( )
82+ return
83+ }
84+
85+ let responseBody = try JSONDecoder ( ) . decode ( BugsnagResponseBody< TestBody> . self , from: params. body)
86+
87+ guard let body = responseBody. events. first? . request? . body else {
88+ XCTFail ( " Unable to parse request body " )
89+ return
90+ }
91+ XCTAssertNil ( body. password, " test that password is removed " )
92+ XCTAssertNil ( body. email, " test that email is removed " )
93+ XCTAssertEqual ( body. hash, TestBody . default. hash, " test that hash is not altered " )
94+ }
95+
96+ func testKeyFiltersWorkInHeaderFields( ) throws {
97+ var capturedSendReportParameters : (
98+ host: String ,
99+ headers: HTTPHeaders ,
100+ body: Data ,
101+ container: Container
102+ ) ?
103+
104+ let reporter = BugsnagReporter (
105+ config: . init( apiKey: " apiKey " , releaseStage: " test " , keyFilters: [ " password " , " email " ] ) ,
106+ sendReport: { host, headers, data, container in
107+ capturedSendReportParameters = ( host, headers, data, container)
108+ return container. future ( Response ( http: HTTPResponse ( status: . ok) , using: container) )
109+ } )
110+ let application = try Application . test ( )
111+ let request = Request ( using: application)
112+ request. http. method = . POST
113+ request. http. body = TestBody . default. httpBody
114+ var headers = request. http. headers
115+ headers. add ( name: HTTPHeaderName ( " password " ) , value: TestBody . default. password!)
116+ headers. add ( name: HTTPHeaderName ( " email " ) , value: TestBody . default. email!)
117+ headers. add ( name: HTTPHeaderName ( " hash " ) , value: TestBody . default. hash!)
118+ request. http. headers = headers
119+
120+ _ = try ! reporter. report ( NotFound ( ) , on: request) . wait ( )
121+
122+ guard let params = capturedSendReportParameters else {
123+ XCTFail ( )
124+ return
125+ }
126+
127+ let responseBody = try JSONDecoder ( ) . decode ( BugsnagResponseBody< TestBody> . self , from: params. body)
128+
129+ guard let responseHeaders = responseBody. events. first? . request? . headers else {
130+ XCTFail ( " Unable to parse response headers " )
131+ return
132+ }
133+
134+ XCTAssertNil ( responseHeaders [ " password " ] , " test that password is removed " )
135+ XCTAssertNil ( responseHeaders [ " email " ] , " test that email is removed " )
136+ XCTAssertEqual ( responseHeaders [ " hash " ] , TestBody . default. hash!, " test that hash is not altered " )
137+ }
138+
139+ func testKeyFiltersWorkInURLQueryParams( ) throws {
140+ var capturedSendReportParameters : (
141+ host: String ,
142+ headers: HTTPHeaders ,
143+ body: Data ,
144+ container: Container
145+ ) ?
146+
147+ let reporter = BugsnagReporter (
148+ config: . init( apiKey: " apiKey " , releaseStage: " test " , keyFilters: [ " password " , " email " ] ) ,
149+ sendReport: { host, headers, data, container in
150+ capturedSendReportParameters = ( host, headers, data, container)
151+ return container. future ( Response ( http: HTTPResponse ( status: . ok) , using: container) )
152+ } )
153+ let application = try Application . test ( )
154+ let request = Request ( using: application)
155+ request. http. url = URL ( string: " http://foo.bar.com/?password= \( TestBody . default. password!) &email= \( TestBody . default. email!) &hash= \( TestBody . default. hash!) " ) !
156+ request. http. method = . POST
157+ request. http. body = TestBody . default. httpBody
158+ var headers = request. http. headers
159+ headers. add ( name: HTTPHeaderName ( " password " ) , value: TestBody . default. password!)
160+ headers. add ( name: HTTPHeaderName ( " email " ) , value: TestBody . default. email!)
161+ headers. add ( name: HTTPHeaderName ( " hash " ) , value: TestBody . default. hash!)
162+ request. http. headers = headers
163+
164+ _ = try ! reporter. report ( NotFound ( ) , on: request) . wait ( )
165+
166+ guard let params = capturedSendReportParameters else {
167+ XCTFail ( )
168+ return
169+ }
170+
171+ let responseBody = try JSONDecoder ( ) . decode ( BugsnagResponseBody< TestBody> . self , from: params. body)
172+
173+ guard let responseURLString = responseBody. events. first? . request? . url else {
174+ XCTFail ( " Unable to parse response url " )
175+ return
176+ }
177+
178+ let urlComponents = URLComponents ( string: responseURLString)
179+ let passwordItem = urlComponents? . queryItems? . filter { $0. name == " password " } . last
180+ let emailItem = urlComponents? . queryItems? . filter { $0. name == " email " } . last
181+ let hashItem = urlComponents? . queryItems? . filter { $0. name == " hash " } . last
182+
183+ XCTAssertNil ( passwordItem, " test that password is removed " )
184+ XCTAssertNil ( emailItem, " test that email is removed " )
185+ XCTAssertEqual ( hashItem? . value, TestBody . default. hash!, " test that hash is not altered " )
186+ }
187+ }
188+
189+ struct TestBody : Codable {
190+ var password : String ?
191+ var email : String ?
192+ var hash : String ?
193+
194+ static var `default` : TestBody {
195+ return . init
( password
: " TopSecret " , email
: " [email protected] " , hash
: " myAwesomeHash " ) 196+ }
197+
198+ var httpBody : HTTPBody {
199+ return try ! HTTPBody ( data: JSONEncoder ( ) . encode ( self ) )
200+ }
201+ }
202+
203+ struct BugsnagResponseBody < T: Codable > : Codable {
204+ struct Event : Codable {
205+ struct Request : Codable {
206+ let body : T ?
207+ let headers : [ String : String ] ?
208+ let url : String ?
209+
210+ // custom decoding needed as the format is JSON string (not JSON object)
211+ init ( from decoder: Decoder ) throws {
212+ let container = try decoder. container ( keyedBy: CodingKeys . self)
213+ let bodyString = try container. decode ( String . self, forKey: . body)
214+ guard let data = bodyString. data ( using: . utf8) else {
215+ throw Abort ( . internalServerError)
216+ }
217+ body = try JSONDecoder ( ) . decode ( T . self, from: data)
218+ headers = try container. decode ( Dictionary . self, forKey: . headers)
219+ url = try container. decode ( String . self, forKey: . url)
220+ }
221+ }
222+ let request : Request ?
223+ }
224+ let apiKey : String
225+ let events : [ Event ]
58226}
0 commit comments