Skip to content

Commit

Permalink
ensure headers are redacted when inspecting http requests & responses (
Browse files Browse the repository at this point in the history
…#3826)

Co-authored-by: Tim <hello@timsmart.co>
  • Loading branch information
juliusmarminge and tim-smart authored Oct 23, 2024
1 parent c5d537f commit 42cd72a
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 23 deletions.
5 changes: 5 additions & 0 deletions .changeset/old-spies-knock.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@effect/platform": patch
---

ensure requests & responses have headers redacted when inspecting
20 changes: 3 additions & 17 deletions packages/platform-browser/src/internal/httpClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,25 +314,11 @@ class ClientResponseImpl extends IncomingMessageImpl<Error.ResponseError> implem
}

toJSON(): unknown {
let body: unknown
try {
body = Effect.runSync(this.json)
} catch (_) {
//
}
try {
body = body ?? Effect.runSync(this.text)
} catch (_) {
//
}
return {
return IncomingMessage.inspect(this, {
_id: "@effect/platform/HttpClientResponse",
request: this.request.toJSON(),
status: this.status,
headers: this.headers,
remoteAddress: this.remoteAddress.toJSON(),
body
}
status: this.status
})
}
}

Expand Down
6 changes: 3 additions & 3 deletions packages/platform/src/HttpIncomingMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as Effect from "effect/Effect"
import * as FiberRef from "effect/FiberRef"
import { dual } from "effect/Function"
import * as Global from "effect/GlobalValue"
import type { Inspectable } from "effect/Inspectable"
import * as Inspectable from "effect/Inspectable"
import * as Option from "effect/Option"
import type * as ParseResult from "effect/ParseResult"
import * as Schema from "effect/Schema"
Expand All @@ -31,7 +31,7 @@ export type TypeId = typeof TypeId
* @since 1.0.0
* @category models
*/
export interface HttpIncomingMessage<E> extends Inspectable {
export interface HttpIncomingMessage<E> extends Inspectable.Inspectable {
readonly [TypeId]: TypeId
readonly headers: Headers.Headers
readonly remoteAddress: Option.Option<string>
Expand Down Expand Up @@ -116,7 +116,7 @@ export const inspect = <E>(self: HttpIncomingMessage<E>, that: object): object =
}
const obj: any = {
...that,
headers: self.headers,
headers: Inspectable.redact(self.headers),
remoteAddress: self.remoteAddress.toJSON()
}
if (body !== undefined) {
Expand Down
2 changes: 1 addition & 1 deletion packages/platform/src/internal/httpClientRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const Proto = {
url: this.url,
urlParams: this.urlParams,
hash: this.hash,
headers: this.headers,
headers: Inspectable.redact(this.headers),
body: this.body.toJSON()
}
},
Expand Down
2 changes: 1 addition & 1 deletion packages/platform/src/internal/httpServerResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class ServerResponseImpl extends Effectable.StructuralClass<ServerResponse.HttpS
_id: "@effect/platform/HttpServerResponse",
status: this.status,
statusText: this.statusText,
headers: this.headers,
headers: Inspectable.redact(this.headers),
cookies: this.cookies.toJSON(),
body: this.body.toJSON()
}
Expand Down
32 changes: 31 additions & 1 deletion packages/platform/test/HttpClient.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import {
Cookies,
FetchHttpClient,
Headers,
HttpClient,
HttpClientRequest,
HttpClientResponse,
UrlParams
} from "@effect/platform"
import { assert, describe, expect, it } from "@effect/vitest"
import { Either, Ref, Struct } from "effect"
import { Either, FiberId, FiberRefs, Inspectable, Ref, Struct } from "effect"
import * as Context from "effect/Context"
import * as Effect from "effect/Effect"
import * as Layer from "effect/Layer"
Expand Down Expand Up @@ -191,4 +192,33 @@ describe("HttpClient", () => {
)
assert.deepStrictEqual(response, { id: 1, userId: 1, title: "delectus aut autem", completed: false })
}).pipe(Effect.provide(JsonPlaceholderLive)))

it("ClientRequest redacts headers", () => {
const request = HttpClientRequest.get(new URL("https://example.com")).pipe(
HttpClientRequest.setHeaders({
"authorization": "foobar"
})
)

const fiberRefs = FiberRefs.unsafeMake(
new Map([
[
Headers.currentRedactedNames,
[[FiberId.none, ["Authorization"]] as const]
] as const
])
)
const r = Inspectable.withRedactableContext(fiberRefs, () => Inspectable.toStringUnknown(request))
const redacted = JSON.parse(r)

assert.deepStrictEqual(redacted, {
_id: "@effect/platform/HttpClientRequest",
method: "GET",
url: "https://example.com/",
urlParams: [],
hash: { _id: "Option", _tag: "None" },
headers: { authorization: "<redacted>" },
body: { _id: "@effect/platform/HttpBody", _tag: "Empty" }
})
})
})

0 comments on commit 42cd72a

Please sign in to comment.