diff --git a/Package.swift b/Package.swift index 06d0b13..f0bef21 100644 --- a/Package.swift +++ b/Package.swift @@ -13,8 +13,8 @@ let package = Package( .library(name: "LoggingELK", targets: ["LoggingELK"]) ], dependencies: [ - .package(url: "https://github.com/apple/swift-log.git", .upToNextMinor(from: "1.4.0")), - .package(url: "https://github.com/swift-server/async-http-client.git", .upToNextMinor(from: "1.5.0")) + .package(url: "https://github.com/apple/swift-log.git", .upToNextMajor(from: "1.4.0")), + .package(url: "https://github.com/swift-server/async-http-client.git", .upToNextMajor(from: "1.5.0")) ], targets: [ .target( diff --git a/Sources/LoggingELK/LogstashLogHandler+HTTPFormatting.swift b/Sources/LoggingELK/LogstashLogHandler+HTTPFormatting.swift index 9e3d3f9..f9e62fd 100644 --- a/Sources/LoggingELK/LogstashLogHandler+HTTPFormatting.swift +++ b/Sources/LoggingELK/LogstashLogHandler+HTTPFormatting.swift @@ -54,6 +54,10 @@ extension LogstashLogHandler { } // Set headers that always stay consistent over all requests + if let authorization = self.authorization { + httpRequest.headers.add(name: "Authorization", value: authorization.value) + } + httpRequest.headers.add(name: "Content-Type", value: "application/json") httpRequest.headers.add(name: "Accept", value: "application/json") // Keep-alive header to keep the connection open diff --git a/Sources/LoggingELK/LogstashLogHandler.swift b/Sources/LoggingELK/LogstashLogHandler.swift index 63ac70f..7d07fb2 100644 --- a/Sources/LoggingELK/LogstashLogHandler.swift +++ b/Sources/LoggingELK/LogstashLogHandler.swift @@ -13,6 +13,7 @@ import AsyncHTTPClient /// `LogstashLogHandler` is a simple implementation of `LogHandler` for directing /// `Logger` output to Logstash via HTTP requests +@available(iOS 13.0, *) public struct LogstashLogHandler: LogHandler { /// The label of the `LogHandler` let label: String @@ -22,6 +23,8 @@ public struct LogstashLogHandler: LogHandler { static var port: Int? /// Specifies if the HTTP connection to Logstash should be encrypted via TLS (so HTTPS instead of HTTP) static var useHTTPS: Bool? + /// Specifies the authorization schema for the HTTP request + static var authorization: Authorizable? /// The `EventLoopGroup` which is used to create the `HTTPClient` static var eventLoopGroup: EventLoopGroup? /// Used to log background activity of the `LogstashLogHandler` and `HTTPClient` @@ -89,6 +92,7 @@ public struct LogstashLogHandler: LogHandler { public static func setup(hostname: String, port: Int, useHTTPS: Bool = false, + authorization: Authorizable? = nil, eventLoopGroup: EventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: (System.coreCount != 1) ? System.coreCount / 2 : 1), backgroundActivityLogger: Logger = Logger(label: "backgroundActivity-logstashHandler"), uploadInterval: TimeAmount = TimeAmount.seconds(3), @@ -101,6 +105,7 @@ public struct LogstashLogHandler: LogHandler { Self.hostname = hostname Self.port = port Self.useHTTPS = useHTTPS + Self.authorization = authorization Self.eventLoopGroup = eventLoopGroup Self.backgroundActivityLogger = backgroundActivityLogger Self.uploadInterval = uploadInterval diff --git a/Sources/LoggingELK/Utils/Authorization.swift b/Sources/LoggingELK/Utils/Authorization.swift new file mode 100644 index 0000000..66659f9 --- /dev/null +++ b/Sources/LoggingELK/Utils/Authorization.swift @@ -0,0 +1,55 @@ +// +// Authentication.swift +// +// +// Created by Oleg Bragin on 09.11.2022. +// + +import Foundation + +/// Describes the property which should be used to set the authorization header +/// to access a remote resource +public protocol Authorizable { + /// Should return authorization header value. + var value: String { get } +} + +/// Defines the most commonly used authroization type names: Basic and Bearer +/// Basically define the first part of overall Authorization header value, e.g.: +/// `Basic `, etc. +public enum AuthorizationType: String { + case basic + case bearer + + public var name: String { + switch self { + case .basic: + return "Basic" + case .bearer: + return "Bearer" + } + } +} + +/// Defines the default way of providing the authorization header to caller +public struct Authorization: Authorizable { + /// Type of authorization + let type: AuthorizationType + /// Token string, which should generated outside + let token: String + + /// Initialize a new authroization structure to provide access to + /// some protected url + /// - Parameters: + /// - type: authorization type, e.g. `basic`, `bearer`, ... + /// - token: generated authorization token + public init(type: AuthorizationType, token: String) { + self.type = type + self.token = token + } + + /// A string concatenated from type name and token itself for authroization header field + public var value: String { + return "\(type.name) \(token)" + } +}