From 2159694f838d9b299c6efc71aba77532be7ed33c Mon Sep 17 00:00:00 2001 From: Honza Dvorsky Date: Tue, 1 Aug 2023 22:04:47 +0200 Subject: [PATCH] Deprecate redactedHeaderFields --- .../Conversion/CurrencyExtensions.swift | 2 +- .../Deprecated_RedactedHeaderFields.swift | 93 +++++++++++++++++++ .../Interface/CurrencyTypes.swift | 62 ------------- ...est_Deprecated_RedactedHeaderFields.swift} | 8 +- 4 files changed, 100 insertions(+), 65 deletions(-) create mode 100644 Sources/OpenAPIRuntime/Deprecated/Deprecated_RedactedHeaderFields.swift rename Tests/OpenAPIRuntimeTests/{Interface/Test_CurrencyTypes.swift => Deprecated/Test_Deprecated_RedactedHeaderFields.swift} (92%) diff --git a/Sources/OpenAPIRuntime/Conversion/CurrencyExtensions.swift b/Sources/OpenAPIRuntime/Conversion/CurrencyExtensions.swift index 4859ea1f..f306d0f7 100644 --- a/Sources/OpenAPIRuntime/Conversion/CurrencyExtensions.swift +++ b/Sources/OpenAPIRuntime/Conversion/CurrencyExtensions.swift @@ -16,7 +16,7 @@ import Foundation extension HeaderField: CustomStringConvertible { public var description: String { let value: String - if HeaderField.redactedHeaderFields.contains(name.lowercased()) { + if HeaderField.internalRedactedHeaderFields.contains(name.lowercased()) { value = "" } else { value = self.value diff --git a/Sources/OpenAPIRuntime/Deprecated/Deprecated_RedactedHeaderFields.swift b/Sources/OpenAPIRuntime/Deprecated/Deprecated_RedactedHeaderFields.swift new file mode 100644 index 00000000..0ae64e12 --- /dev/null +++ b/Sources/OpenAPIRuntime/Deprecated/Deprecated_RedactedHeaderFields.swift @@ -0,0 +1,93 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftOpenAPIGenerator open source project +// +// Copyright (c) 2023 Apple Inc. and the SwiftOpenAPIGenerator project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftOpenAPIGenerator project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +#if canImport(Darwin) +import Foundation +#else +@preconcurrency import Foundation +#endif + +/// A protected-by-locks storage for ``redactedHeaderFields``. +private class RedactedHeadersStorage: @unchecked Sendable { + /// The underlying storage of ``redactedHeaderFields``, + /// protected by a lock. + private var _locked_redactedHeaderFields: Set = HeaderField.defaultRedactedHeaderFields + + /// The header fields to be redacted. + var redactedHeaderFields: Set { + get { + lock.lock() + defer { + lock.unlock() + } + return _locked_redactedHeaderFields + } + set { + lock.lock() + defer { + lock.unlock() + } + _locked_redactedHeaderFields = newValue + } + } + + /// The lock used for protecting access to `_locked_redactedHeaderFields`. + private let lock: NSLock = { + let lock = NSLock() + lock.name = "com.apple.swift-openapi-runtime.lock.redactedHeaderFields" + return lock + }() +} + +extension HeaderField { + /// Names of the header fields whose values should be redacted. + /// + /// All header field names are lowercased when added to the set. + /// + /// The values of header fields with the provided names will are replaced + /// with "" when using `HeaderField.description`. + /// + /// Use this to avoid leaking sensitive tokens into application logs. + @available(*, deprecated, message: "This feature is deprecated and will be removed in a future version.") + public static var redactedHeaderFields: Set { + set { + internalRedactedHeaderFields = newValue + } + get { + internalRedactedHeaderFields + } + } + + /// Names of the header fields whose values should be redacted. + /// + /// Should be called by code in the runtime library to avoid emitting a deprecation warning. + internal static var internalRedactedHeaderFields: Set { + set { + // Save lowercased versions of the header field names to make + // membership checking O(1). + redactedHeadersStorage.redactedHeaderFields = Set(newValue.map { $0.lowercased() }) + } + get { + return redactedHeadersStorage.redactedHeaderFields + } + } + + /// The default header field names whose values are redacted. + public static let defaultRedactedHeaderFields: Set = [ + "authorization", + "cookie", + "set-cookie", + ] + + private static let redactedHeadersStorage = RedactedHeadersStorage() +} diff --git a/Sources/OpenAPIRuntime/Interface/CurrencyTypes.swift b/Sources/OpenAPIRuntime/Interface/CurrencyTypes.swift index 94e962c1..aab24761 100644 --- a/Sources/OpenAPIRuntime/Interface/CurrencyTypes.swift +++ b/Sources/OpenAPIRuntime/Interface/CurrencyTypes.swift @@ -18,38 +18,6 @@ import Foundation @preconcurrency import Foundation #endif -/// A protected-by-locks storage for ``redactedHeaderFields``. -private class RedactedHeadersStorage: @unchecked Sendable { - /// The underlying storage of ``redactedHeaderFields``, - /// protected by a lock. - private var _locked_redactedHeaderFields: Set = HeaderField.defaultRedactedHeaderFields - - /// The header fields to be redacted. - var redactedHeaderFields: Set { - get { - lock.lock() - defer { - lock.unlock() - } - return _locked_redactedHeaderFields - } - set { - lock.lock() - defer { - lock.unlock() - } - _locked_redactedHeaderFields = newValue - } - } - - /// The lock used for protecting access to `_locked_redactedHeaderFields`. - private let lock: NSLock = { - let lock = NSLock() - lock.name = "com.apple.swift-openapi-runtime.lock.redactedHeaderFields" - return lock - }() -} - /// A header field used in an HTTP request or response. public struct HeaderField: Equatable, Hashable, Sendable { @@ -69,36 +37,6 @@ public struct HeaderField: Equatable, Hashable, Sendable { } } -extension HeaderField { - /// Names of the header fields whose values should be redacted. - /// - /// All header field names are lowercased when added to the set. - /// - /// The values of header fields with the provided names will are replaced - /// with "" when using `HeaderField.description`. - /// - /// Use this to avoid leaking sensitive tokens into application logs. - public static var redactedHeaderFields: Set { - set { - // Save lowercased versions of the header field names to make - // membership checking O(1). - redactedHeadersStorage.redactedHeaderFields = Set(newValue.map { $0.lowercased() }) - } - get { - return redactedHeadersStorage.redactedHeaderFields - } - } - - /// The default header field names whose values are redacted. - public static let defaultRedactedHeaderFields: Set = [ - "authorization", - "cookie", - "set-cookie", - ] - - private static let redactedHeadersStorage = RedactedHeadersStorage() -} - /// Describes the HTTP method used in an OpenAPI operation. /// /// https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#fixed-fields-7 diff --git a/Tests/OpenAPIRuntimeTests/Interface/Test_CurrencyTypes.swift b/Tests/OpenAPIRuntimeTests/Deprecated/Test_Deprecated_RedactedHeaderFields.swift similarity index 92% rename from Tests/OpenAPIRuntimeTests/Interface/Test_CurrencyTypes.swift rename to Tests/OpenAPIRuntimeTests/Deprecated/Test_Deprecated_RedactedHeaderFields.swift index a17be6d5..1f7bd70a 100644 --- a/Tests/OpenAPIRuntimeTests/Interface/Test_CurrencyTypes.swift +++ b/Tests/OpenAPIRuntimeTests/Deprecated/Test_Deprecated_RedactedHeaderFields.swift @@ -12,10 +12,11 @@ // //===----------------------------------------------------------------------===// import XCTest -import OpenAPIRuntime +@_spi(Generated)@testable import OpenAPIRuntime -final class Test_CurrencyTypes: Test_Runtime { +final class Test_Deprecated_RedactedHeaderFields: Test_Runtime { + @available(*, deprecated) func _resetRedactedHeaderFields() { HeaderField.redactedHeaderFields = HeaderField.defaultRedactedHeaderFields } @@ -35,11 +36,13 @@ final class Test_CurrencyTypes: Test_Runtime { } } + @available(*, deprecated) override func tearDown() async throws { _resetRedactedHeaderFields() try await super.tearDown() } + @available(*, deprecated) func testDefaultRedactedHeaderFields() { XCTAssertEqual( HeaderField.redactedHeaderFields, @@ -51,6 +54,7 @@ final class Test_CurrencyTypes: Test_Runtime { ) } + @available(*, deprecated) func testCustomizeExtraRedactedHeaderField() { XCTAssertEqual( HeaderField.redactedHeaderFields,