diff --git a/LICENSE b/LICENSE
index 7e1db96..f2a0d74 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
 MIT License
 
-Copyright (c) 2023 Viktor Gidlöf
+Copyright (c) 2024 Viktor Gidlöf
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/Sources/Extensions/DataTaskPublisher.swift b/Sources/Extensions/DataTaskPublisher.swift
deleted file mode 100644
index cc5a2b4..0000000
--- a/Sources/Extensions/DataTaskPublisher.swift
+++ /dev/null
@@ -1,58 +0,0 @@
-//
-//  DataTaskPublisher.swift
-//  Networking
-//
-//  Created by Viktor Gidlöf.
-//
-
-import Foundation
-import Combine
-
-public extension URLSession.DataTaskPublisher {
-    /// Log the incoming response to the console
-    /// - parameter printJSON: A bool value that determines if the json respons is also printed to the console. Defaults to true.
-    /// - returns: The current publisher in the pipeline
-    func logResponse(printJSON: Bool = true) -> Publishers.HandleEvents<Self> {
-        handleEvents(receiveOutput: { value in
-            guard let httpResponse = value.response as? HTTPURLResponse,
-                  let url = httpResponse.url?.absoluteString,
-                  let comps = URLComponents(string: url),
-                  let host = comps.host
-            else { return }
-
-            Swift.print("♻️ Incoming response from \(host) @ \(Date())")
-
-            let statusCode = httpResponse.statusCode
-            let statusCodeString = HTTPURLResponse.localizedString(forStatusCode: statusCode)
-            let path = comps.path
-
-            var printOutput = "~ \(path)\n"
-            printOutput += "Status-Code: \(statusCode)\n"
-            printOutput += "Localized Status-Code: \(statusCodeString)\n"
-
-            httpResponse.allHeaderFields.forEach { key, value in
-                if key.description == HTTP.Header.Field.contentLength || key.description == HTTP.Header.Field.contentType {
-                    printOutput += "\(key): \(value)\n"
-                }
-            }
-
-            Swift.print(printOutput)
-            if printJSON {
-                Swift.print("JSON response:")
-                Swift.print(value.data.prettyPrinted ?? "")
-            }
-        })
-    }
-}
-
-// MARK: -
-private extension Data {
-
-    /// Convert data into an optional pretty printed json string.
-    var prettyPrinted: String? {
-        guard let object = try? JSONSerialization.jsonObject(with: self, options: []),
-              let data = try? JSONSerialization.data(withJSONObject: object, options: [.prettyPrinted])
-        else { return nil }
-        return String(data: data, encoding: .utf8)
-    }
-}
diff --git a/Sources/Extensions/String.swift b/Sources/Extensions/String.swift
index 37286d9..312f7bb 100644
--- a/Sources/Extensions/String.swift
+++ b/Sources/Extensions/String.swift
@@ -10,8 +10,8 @@ import Foundation
 public extension String {
     /// Create a URL from the string
     /// - returns: A new URL based on the given string value
-    func asURL() -> URL {
-        guard let url = URL(string: self) else { fatalError("The URL could not be created ❌ This should never happen!") }
+    func asURL() -> URL? {
+        guard let url = URL(string: self) else { return nil }
         return url
     }
 
@@ -21,4 +21,45 @@ public extension String {
     func basicAuthentication(password: String) -> String {
         Data("\(self):\(password)".utf8).base64EncodedString()
     }
+
+    static func logResponse(_ value: (data: Data, response: URLResponse), printJSON: Bool) {
+        guard let httpResponse = value.response as? HTTPURLResponse,
+              let url = httpResponse.url?.absoluteString,
+              let comps = URLComponents(string: url),
+              let host = comps.host
+        else { return }
+
+        print("♻️ Incoming response from \(host) @ \(Date())")
+
+        let statusCode = httpResponse.statusCode
+        let statusCodeString = HTTPURLResponse.localizedString(forStatusCode: statusCode)
+        let path = comps.path
+
+        var printOutput = "~ \(path)\n"
+        printOutput += "Status-Code: \(statusCode)\n"
+        printOutput += "Localized Status-Code: \(statusCodeString)\n"
+
+        httpResponse.allHeaderFields.forEach { key, value in
+            if key.description == HTTP.Header.Field.contentLength || key.description == HTTP.Header.Field.contentType {
+                printOutput += "\(key): \(value)\n"
+            }
+        }
+
+        print(printOutput)
+        if printJSON {
+            print("JSON response:")
+            print(value.data.prettyPrinted ?? "")
+        }
+    }
+}
+
+// MARK: -
+private extension Data {
+    /// Convert data into an optional pretty printed json string.
+    var prettyPrinted: String? {
+        guard let object = try? JSONSerialization.jsonObject(with: self, options: []),
+              let data = try? JSONSerialization.data(withJSONObject: object, options: [.prettyPrinted])
+        else { return nil }
+        return String(data: data, encoding: .utf8)
+    }
 }
diff --git a/Sources/Extensions/URLRequest.swift b/Sources/Extensions/URLRequest.swift
index 676c7d9..1a0f7d1 100644
--- a/Sources/Extensions/URLRequest.swift
+++ b/Sources/Extensions/URLRequest.swift
@@ -34,7 +34,11 @@ public extension URLRequest {
 
     /// Print outgoing request information to the console
     func log() {
-        guard let url = url?.absoluteString, let components = URLComponents(string: url), let method = httpMethod, let host = components.host else { return }
+        guard let url = url?.absoluteString,
+              let components = URLComponents(string: url),
+              let method = httpMethod,
+              let host = components.host
+        else { return }
 
         print("⚡️ Outgoing request to \(host) @ \(Date())")
 
diff --git a/Sources/ServerConfig/ServerConfig.swift b/Sources/ServerConfig/ServerConfig.swift
index 2e754cf..439c750 100644
--- a/Sources/ServerConfig/ServerConfig.swift
+++ b/Sources/ServerConfig/ServerConfig.swift
@@ -2,56 +2,93 @@
 //  ServerConfig.swift
 //  Networking
 //
-//  Created by Viktor Gidlöf.
+//  Created by VG on 2024-11-13.
 //
 
 import Foundation
 
-/// An object for creating a server configuration for the backend API
-open class ServerConfig {
+public protocol ServerConfigurable {
+    var baseURL: URL { get }
+    func header(forRequest request: Requestable) -> HTTP.Header
+}
 
+// MARK: -
+public struct ServerConfig: ServerConfigurable {
     // MARK: Private properties
-    private let tokenProvider: TokenProvidable?
+    private let additionalHeaders: HTTP.Header
 
     // MARK: - Public properties
+    public let userAgent: String?
+    /// A provider for authorization tokens used to authenticate requests; `nil` if no authentication is needed.
+    public let tokenProvider: TokenProvidable?
     /// The base URL for the server
     public let baseURL: URL
 
-    /// Init the server configuration
-    /// - parameters:
-    ///     - baseURL: The given base URL used for this server config
-    ///     - tokenProvider: An optional token provider object used to authenticate requests. Defaults to `nil`.
-    public init(baseURL: String, tokenProvider: TokenProvidable? = nil) {
-        self.baseURL = baseURL.asURL()
+    // MARK: - Initialization
+    /// Initializes a new instance of `ServerConfigV2` with the specified configuration details.
+    /// - Parameters:
+    ///   - baseURL: A `String` representing the base URL for the server. This URL will be used as the primary endpoint for all requests.
+    ///   - userAgent: An optional `String` representing the user agent to include in the request headers. If not provided, it defaults to a string combining `name` and `version`.
+    ///   - additionalHeaders: An optional dictionary of additional headers to be merged into the default headers for each request. The default value is an empty dictionary.
+    ///   - tokenProvider: An optional `TokenProvidable` object used to authenticate requests. This provider supplies authorization tokens when required by a request. Defaults to `nil`, meaning no token is provided.
+    /// - Returns: A configured instance of `ServerConfigV2` with the specified parameters.
+    public init?(
+        baseURL: String,
+        userAgent: String? = "\(name)/\(version)",
+        additionalHeaders: HTTP.Header = [:],
+        tokenProvider: TokenProvidable? = nil
+    ) {
+        guard let url = baseURL.asURL() else { return nil }
+        self.baseURL = url
+        self.userAgent = userAgent
+        self.additionalHeaders = additionalHeaders
         self.tokenProvider = tokenProvider
     }
+}
 
-    /// Create a HTTP header for the requests.
-    /// Subclasses can call `super` if they need to implement the standard authentication.
-    /// Don't call `super` if you want to have a fully custom HTTP header implementation.
-    /// - parameter request: The given request to set up the header with
-    /// - returns: A new `HTTP.Header` dictionary
-    open func header(forRequest request: Requestable) -> HTTP.Header {
-        var header = HTTP.Header()
-        header[HTTP.Header.Field.userAgent] = "\(name)/\(version)"
-        header[HTTP.Header.Field.host] = baseURL.host
-
-        if let contentType = request.contentType {
-            header[HTTP.Header.Field.contentType] = contentType
-        }
+// MARK: - Public functions
+public extension ServerConfig {
+    func header(forRequest request: Requestable) -> HTTP.Header {
+        var headers = HTTP.Header()
+
+        // Base headers
+        if let host = baseURL.host { headers[HTTP.Header.Field.host] = host }
+        if let userAgent = userAgent { headers[HTTP.Header.Field.userAgent] = userAgent }
+        if let contentType = request.contentType { headers[HTTP.Header.Field.contentType] = contentType }
 
-        guard let tokenProvider = tokenProvider else { return header }
+        // Add any additional configured headers
+        headers.merge(additionalHeaders) { _, new in new }
+
+        guard let tokenProvider else { return headers }
 
         switch tokenProvider.token {
         case .success(let token):
-            switch request.authorization {
-            case .bearer: header[HTTP.Header.Field.auth] = String(format: HTTP.Header.Field.bearer, token)
-            case .basic: header[HTTP.Header.Field.auth] = String(format: HTTP.Header.Field.basic, token)
-            case .none: break
-            }
-        case .failure:
-            break
+            guard let authHeader = authorizationHeader(for: request.authorization, token: token) else { break }
+            headers[HTTP.Header.Field.auth] = authHeader
+        case .failure: break
+        }
+        return headers
+    }
+}
+
+// MARK: - Convenience Initializers
+public extension ServerConfig {
+    static func basic(baseURL: String) -> ServerConfig? {
+        .init(baseURL: baseURL)
+    }
+
+    static func authenticated(baseURL: String, tokenProvider: TokenProvidable) -> ServerConfig? {
+        .init(baseURL: baseURL, tokenProvider: tokenProvider)
+    }
+}
+
+// MARK: - Private functions
+private extension ServerConfig {
+    func authorizationHeader(for type: Request.Authorization, token: String) -> String? {
+        switch type {
+        case .bearer: return String(format: HTTP.Header.Field.bearer, token)
+        case .basic: return String(format: HTTP.Header.Field.basic, token)
+        case .none: return nil
         }
-        return header
     }
 }
diff --git a/Sources/Service/DownloadPublisher.swift b/Sources/Service/DownloadPublisher.swift
deleted file mode 100644
index 8e39d14..0000000
--- a/Sources/Service/DownloadPublisher.swift
+++ /dev/null
@@ -1,101 +0,0 @@
-//
-//  DownloadPublisher.swift
-//  Networking
-//
-//  Created by Viktor Gidlöf.
-//
-
-import Foundation
-import Combine
-
-public extension Network.Service {
-    /// A downloader structure object used to track and progress file downloads
-    struct Downloader: Publisher {
-        public typealias Failure = Error
-
-        // MARK: Private properties
-        private let url: URL
-
-        // MARK: - Public properties
-        /// The publisher output
-        public enum Output {
-            /// The destination case containing the temporary file destination
-            case destination(URL)
-            /// The progress case containing the download progress as a `Float` value
-            case progress(Float)
-        }
-
-        // MARK: - Init
-        /// Initialize the download publisher
-        /// - parameter url: The given file URL
-        init(url: URL) {
-            self.url = url
-        }
-
-        // MARK: - Public functions
-        public func receive<S: Subscriber>(subscriber: S) where Output == S.Input, Failure == S.Failure {
-            let subscription = DownloadSubscription(subscriber, url: url)
-            subscriber.receive(subscription: subscription)
-        }
-    }
-}
-
-// MARK: -
-private extension Network.Service {
-
-    /// A subscriber object that conforms to `URLSessionDownloadDelegate` used to report and track URL session downloads
-    private final class DownloadSubscription<S: Subscriber>: Network.Service.Sub<S>, URLSessionDownloadDelegate where S.Input == Downloader.Output, S.Failure == Error {
-        // MARK: Private properties
-        private var session: URLSession!
-        private let url: URL
-
-        // MARK: - Init
-        /// Init the subscriber
-        /// - parameters:
-        ///     - subscriber: The given subscriber
-        ///     - url: The URL to the file to download
-        init(_ subscriber: S, url: URL) {
-            self.url = url
-            super.init(subscriber: subscriber)
-
-            session = URLSession(configuration: .default, delegate: self, delegateQueue: .main)
-            session.downloadTask(with: url).resume()
-            _ = subscriber.receive(.progress(0.0))
-        }
-
-        // MARK: - URLSessionDownloadDelegate
-        func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
-            let progress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
-            _ = subscriber?.receive(.progress(progress))
-        }
-
-        func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
-            _ = subscriber?.receive(.destination(location))
-            subscriber?.receive(completion: .finished)
-        }
-
-        func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
-            guard let error = error else { return }
-            subscriber?.receive(completion: .failure(error))
-        }
-    }
-}
-
-// MARK: -
-private extension Network.Service {
-    /// A custom subscriber object used for creating subscriptions
-    class Sub<S: Subscriber>: NSObject, Subscription {
-        // MARK: Private properties
-        private(set) var subscriber: S?
-
-        // MARK: - Init
-        init(subscriber: S) {
-            self.subscriber = subscriber
-            super.init()
-        }
-
-        // MARK: - Public functions
-        func request(_ demand: Subscribers.Demand) {}
-        func cancel() { subscriber = nil }
-    }
-}
diff --git a/Sources/Service/Downloader.swift b/Sources/Service/Downloader.swift
new file mode 100644
index 0000000..16cc1f6
--- /dev/null
+++ b/Sources/Service/Downloader.swift
@@ -0,0 +1,101 @@
+//
+//  Downloader.swift
+//  Networking
+//
+//  Created by Viktor Gidlöf.
+//
+
+import Foundation
+
+public extension Network.Service {
+    /// A downloader actor that handles file downloads with progress tracking
+    actor Downloader {
+        // MARK: Private properties
+        private let url: URL
+        private let session: URLSession
+        private var downloadTask: URLSessionDownloadTask?
+        private var progressContinuation: AsyncStream<Float>.Continuation?
+
+        // MARK: - Init
+        init(url: URL, session: URLSession = .shared) {
+            self.url = url
+            self.session = session
+        }
+    }
+}
+
+// MARK: - Public functions
+public extension Network.Service.Downloader {
+    /// Start downloading the file and track progress
+    /// - Returns: A tuple containing the downloaded file URL and an AsyncStream of progress updates
+    func download() async throws -> (URL, AsyncStream<Float>) {
+        let (stream, continuation) = AsyncStream<Float>.makeStream()
+        progressContinuation = continuation
+        continuation.yield(0.0)
+
+        let downloadedURL = try await withCheckedThrowingContinuation { continuation in
+            let delegate = DownloadDelegate { [weak self] result in
+                Task { [weak self] in
+                    await self?.handleCompletion(result, continuation: continuation)
+                }
+            } progressHandler: { [weak self] progress in
+                Task { [weak self] in
+                    await self?.handleProgress(progress)
+                }
+            }
+            let session = URLSession(configuration: .default, delegate: delegate, delegateQueue: nil)
+            let task = session.downloadTask(with: url)
+            downloadTask = task
+            task.resume()
+        }
+        return (downloadedURL, stream)
+    }
+
+    /// Cancel the ongoing download
+    func cancel() {
+        downloadTask?.cancel()
+        progressContinuation?.finish()
+    }
+}
+
+// MARK: - Private functions
+private extension Network.Service.Downloader {
+    func handleCompletion(_ result: Result<URL, Error>, continuation: CheckedContinuation<URL, Error>) {
+        switch result {
+        case .success(let url): continuation.resume(returning: url)
+        case .failure(let error): continuation.resume(throwing: error)
+        }
+        progressContinuation?.finish()
+    }
+    
+    func handleProgress(_ progress: Float) {
+        progressContinuation?.yield(progress)
+    }
+}
+
+// MARK: - Download Delegate
+private final class DownloadDelegate: NSObject, URLSessionDownloadDelegate {
+    private let completionHandler: (Result<URL, Error>) -> Void
+    private let progressHandler: (Float) -> Void
+    
+    init(completionHandler: @escaping (Result<URL, Error>) -> Void, progressHandler: @escaping (Float) -> Void) {
+        self.completionHandler = completionHandler
+        self.progressHandler = progressHandler
+        super.init()
+    }
+    
+    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
+        completionHandler(.success(location))
+    }
+    
+    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
+        let progress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
+        progressHandler(progress)
+    }
+    
+    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
+        if let error = error {
+            completionHandler(.failure(error))
+        }
+    }
+}
diff --git a/Sources/Service/NetworkService.swift b/Sources/Service/NetworkService.swift
index 79caf30..f1a8cd0 100644
--- a/Sources/Service/NetworkService.swift
+++ b/Sources/Service/NetworkService.swift
@@ -9,7 +9,7 @@ import Foundation
 import Combine
 
 public let name = "Networking"
-public let version = "0.8.9"
+public let version = "0.9.0"
 
 public enum Network {
     /// A network service object used to make requests to the backend.
@@ -30,65 +30,61 @@ public enum Network {
             self.decoder = decoder
             self.server = server
         }
-
-        // MARK: - Private functions
-        private func dataTaskPublisher(_ request: Requestable, logResponse: Bool) throws -> AnyPublisher<URLSession.DataTaskPublisher.Output, Error> {
-            let config = Request.Config(request: request, server: server)
-            let urlRequest = try URLRequest(withConfig: config)
-            urlRequest.log()
-
-            return session.dataTaskPublisher(for: urlRequest)
-                .logResponse(printJSON: logResponse)
-                .receive(on: RunLoop.main)
-                .tryMap { $0 }
-                .eraseToAnyPublisher()
-        }
     }
 }
 
-// MARK: -
+// MARK: - Public functions
 public extension Network.Service {
-    /// Create a new publisher that contains a decoded data model object
+    /// Send a request and decode the response into a data model object
     /// - parameters:
     ///     - request: The request to send over the network
     ///     - logResponse: A boolean value that determines if the json response should be printed to the console. Defaults to false.
-    /// - throws: An error if the data task publisher fails for any reason
-    /// - returns: A new publisher with the given data model object or an error
-    func request<DataModel: Decodable>(_ request: Requestable, logResponse: Bool = false) throws -> AnyPublisher<DataModel, Error> {
-        try dataPublisher(request, logResponse: logResponse)
-            .decode(type: DataModel.self, decoder: decoder)
-            .eraseToAnyPublisher()
+    /// - throws: An error if the request fails for any reason
+    /// - returns: The decoded data model object
+    func request<DataModel: Decodable>(_ request: Requestable, logResponse: Bool = false) async throws -> DataModel {
+        let (data, _) = try await makeDataRequest(request, logResponse: logResponse)
+        return try decoder.decode(DataModel.self, from: data)
     }
 
-    /// Create a new publisher that contains the response data
+    /// Send a request and return the raw response data
     /// - parameters:
     ///     - request: The request to send over the network
     ///     - logResponse: A boolean value that determines if the json response should be printed to the console. Defaults to false.
-    /// - throws: An error if the data task publisher fails for any reason
-    /// - returns: A new publisher with the data or an error
-    func dataPublisher(_ request: Requestable, logResponse: Bool = false) throws -> AnyPublisher<Data, Error> {
-        try dataTaskPublisher(request, logResponse: logResponse)
-            .map(\.data)
-            .eraseToAnyPublisher()
+    /// - throws: An error if the request fails for any reason
+    /// - returns: The raw response data
+    func data(_ request: Requestable, logResponse: Bool = false) async throws -> Data {
+        let (data, _) = try await makeDataRequest(request, logResponse: logResponse)
+        return data
     }
 
-    /// Create a new publisher that contains the HTTP status code
+    /// Send a request and return the HTTP status code
     /// - parameters:
     ///     - request: The request to send over the network
     ///     - logResponse: A boolean value that determines if the json response should be printed to the console. Defaults to false.
-    /// - throws: An error if the data task publisher fails for any reason
-    /// - returns: A new publisher with a bool value that determines if the request succeeded
-    func responsePublisher(_ request: Requestable, logResponse: Bool = false) throws -> AnyPublisher<HTTP.StatusCode, Error> {
-        try dataTaskPublisher(request, logResponse: logResponse)
-            .compactMap { $0.response as? HTTPURLResponse }
-            .map { HTTP.StatusCode(rawValue: $0.statusCode) ?? .unknown }
-            .eraseToAnyPublisher()
+    /// - throws: An error if the request fails for any reason
+    /// - returns: The HTTP status code
+    func response(_ request: Requestable, logResponse: Bool = false) async throws -> HTTP.StatusCode {
+        let (_, response) = try await makeDataRequest(request, logResponse: logResponse)
+        guard let httpResponse = response as? HTTPURLResponse else { return .unknown }
+        return HTTP.StatusCode(rawValue: httpResponse.statusCode) ?? .unknown
     }
 
-    /// Create a new publisher that publishes file download progress and the destination of the temporary file
-    /// - parameter url: The URL to the file to download
-    /// - returns: A new download publisher with the file download progress and destination URL
-    func downloadPublisher(url: URL) -> Network.Service.Downloader {
+    /// Creates a new instance of `Network.Service.Downloader` configured with the specified URL.
+    /// - Parameter url: The `URL` from which the downloader will retrieve data.
+    /// - Returns: A configured `Network.Service.Downloader` instance for downloading data from the given URL.
+    func downloader(url: URL) -> Network.Service.Downloader {
         Network.Service.Downloader(url: url)
     }
 }
+
+// MARK: - Private functions
+private extension Network.Service {
+    func makeDataRequest(_ request: Requestable, logResponse: Bool) async throws -> (Data, URLResponse) {
+        let urlRequest = try request.configure(withServer: server)
+        let (data, response) = try await session.data(for: urlRequest)
+        if logResponse {
+            String.logResponse((data, response), printJSON: logResponse)
+        }
+        return (data, response)
+    }
+}
diff --git a/Tests/NetworkingTests/NetworkingTests.swift b/Tests/NetworkingTests/NetworkingTests.swift
index 9349c8e..87c96e8 100644
--- a/Tests/NetworkingTests/NetworkingTests.swift
+++ b/Tests/NetworkingTests/NetworkingTests.swift
@@ -3,70 +3,38 @@ import Combine
 @testable import Networking
 
 final class NetworkingTests: XCTestCase {
-
-    private let serverConfig = ServerConfig(baseURL: "https://reqres.in/api")
+    private let serverConfig = ServerConfig(baseURL: "https://reqres.in/api")!
     private lazy var networkService = Network.Service(server: serverConfig)
-    private var cancel: AnyCancellable?
 
-    func testMockUser() throws {
+    func testMockUser() async throws {
         let user = MockGetRequest.user(1)
-        let expectation = expectation(description: "Awaiting mock user")
-
-        cancel = try networkService.request(user).sink { (result: Result<MockUserResponse, Error>) in
-            expectation.fulfill()
-            switch result {
-            case .success(let user): XCTAssertTrue(user.data.id == 1)
-            case .failure(let error): XCTFail(error.localizedDescription)
-            }
-        }
-        waitForExpectations(timeout: 30.0)
+        let response: MockUserResponse = try await networkService.request(user)
+        XCTAssertTrue(response.data.id == 1)
     }
 
-    func testMockUsers() throws {
+    func testMockUsers() async throws {
         let users = MockGetRequest.users
-        let expectation = expectation(description: "Awaiting mock users")
-
-        cancel = try networkService.request(users).sink { (result: Result<MockUsersRepsonse, Error>) in
-            expectation.fulfill()
-            switch result {
-            case .success(let user): XCTAssertTrue(!user.data.isEmpty)
-            case .failure(let error): XCTFail(error.localizedDescription)
-            }
-        }
-        waitForExpectations(timeout: 30.0)
+        let response: MockUsersRepsonse = try await networkService.request(users)
+        XCTAssertTrue(!response.data.isEmpty)
     }
 
-    func testMockPostUser() throws {
+    func testMockPostUser() async throws {
         let model = MockPostUserModel(name: "Viktor", job: "iOS Engineer")
         let users = MockPostRequest.user(model)
-        let expectation = expectation(description: "Awaiting mock post users")
-
-        cancel = try networkService.responsePublisher(users).sink { result in
-            expectation.fulfill()
-            switch result {
-            case .success(let responseCode): XCTAssertTrue(responseCode == .created)
-            case .failure(let error): XCTFail(error.localizedDescription)
-            }
-        }
-        waitForExpectations(timeout: 30.0)
+        let responseCode = try await networkService.response(users)
+        XCTAssertTrue(responseCode == .created)
     }
 
-    func testDownloadImageFile() {
+    func testDownloadImageFile() async throws {
         let url = "https://media.viktorgidlof.com/2022/12/djunglehorse.jpg".asURL()
-        let expectation = expectation(description: "Awaiting image download progress")
+        let downloader = Network.Service.Downloader(url: url!)
+        let (fileURL, progress) = try await downloader.download()
 
-        cancel = networkService.downloadPublisher(url: url).sink { result in
-            switch result {
-            case .success(.destination(let url)):
-                expectation.fulfill()
-                XCTAssertTrue(url.lastPathComponent.split(separator: ".").last == "tmp")
-            case .success(.progress(let progress)):
-                print("Download progress: \(progress)")
-            case .failure(let error):
-                expectation.fulfill()
-                XCTFail(error.localizedDescription)
+        Task {
+            for await progressValue in progress {
+                print("Download progress: \(progressValue)")
             }
         }
-        waitForExpectations(timeout: 30.0)
+        XCTAssertTrue(fileURL.lastPathComponent.split(separator: ".").last == "tmp")
     }
 }
diff --git a/Tests/NetworkingTests/ServerConfigTests.swift b/Tests/NetworkingTests/ServerConfigTests.swift
new file mode 100644
index 0000000..d9212d9
--- /dev/null
+++ b/Tests/NetworkingTests/ServerConfigTests.swift
@@ -0,0 +1,108 @@
+//
+//  ServerConfigTests.swift
+//  Networking
+//
+//  Created by VG on 2024-11-13.
+//
+
+import XCTest
+@testable import Networking
+
+final class ServerConfigV2Tests: XCTestCase {
+    private let validURLString = "https://api.example.com"
+    private let tokenProviderMock = MockTokenProvider()
+    private var config: ServerConfig!
+
+    override func setUp() {
+        super.setUp()
+        config = ServerConfig(baseURL: validURLString, tokenProvider: tokenProviderMock)
+    }
+
+    override func tearDown() {
+        config = nil
+        super.tearDown()
+    }
+
+    // MARK: - Initialization Tests
+    func testInitialization_withValidURL_shouldSucceed() {
+        let config = ServerConfig(baseURL: validURLString, userAgent: "TestAgent/1.0")
+        XCTAssertEqual(config?.baseURL.absoluteString, validURLString)
+        XCTAssertEqual(config?.userAgent, "TestAgent/1.0")
+    }
+
+    func testInitialization_withInvalidURL_shouldReturnNil() {
+        let config = ServerConfig(baseURL: "") // <-- Invalid URL string
+        XCTAssertNil(config)
+    }
+
+    // MARK: - Header Generation Tests
+    func testHeaderGeneration_includesBaseHeaders() {
+        let request = MockRequestable(authorization: .none)
+        let headers = config.header(forRequest: request)
+        XCTAssertEqual(headers[HTTP.Header.Field.host], config.baseURL.host)
+    }
+    
+    func testHeaderGeneration_includesAdditionalHeaders() {
+        let additionalHeaders = ["X-Custom-Header": "CustomValue"]
+        let config = ServerConfig(baseURL: validURLString, additionalHeaders: additionalHeaders)
+        let headers = config?.header(forRequest: MockRequestable(authorization: .none))
+        XCTAssertEqual(headers?["X-Custom-Header"], "CustomValue")
+    }
+
+    func testHeaderGeneration_withBearerToken_includesAuthorizationHeader() {
+        tokenProviderMock.tokenResult = .success("sampleToken")
+        let request = MockRequestable(authorization: .bearer)
+        let headers = config.header(forRequest: request)
+        XCTAssertEqual(headers[HTTP.Header.Field.auth], "Bearer sampleToken")
+    }
+
+    func testHeaderGeneration_withBasicToken_includesAuthorizationHeader() {
+        tokenProviderMock.tokenResult = .success("sampleToken")
+        let request = MockRequestable(authorization: .basic)
+        let headers = config.header(forRequest: request)
+        XCTAssertEqual(headers[HTTP.Header.Field.auth], "Basic sampleToken")
+    }
+
+    func testHeaderGeneration_withTokenProviderFailure_excludesAuthorizationHeader() {
+        tokenProviderMock.tokenResult = .failure(.missing)
+        let request = MockRequestable(authorization: .bearer)
+        let headers = config.header(forRequest: request)
+        XCTAssertNil(headers[HTTP.Header.Field.auth])
+    }
+
+    // MARK: - Convenience Initializers Tests
+    func testBasicInitializer_createsConfigurationWithDefaultValues() {
+        let config = ServerConfig.basic(baseURL: validURLString)
+        XCTAssertEqual(config?.baseURL.absoluteString, validURLString)
+        XCTAssertNil(config?.tokenProvider)
+    }
+
+    func testAuthenticatedInitializer_createsConfigurationWithTokenProvider() {
+        let config = ServerConfig.authenticated(baseURL: validURLString, tokenProvider: tokenProviderMock)
+        XCTAssertEqual(config?.baseURL.absoluteString, validURLString)
+        XCTAssertNotNil(config?.tokenProvider)
+    }
+}
+
+// MARK: - Mocks
+
+private class MockTokenProvider: TokenProvidable {
+    var tokenResult: Result<String, TokenProvidableError> = .failure(.missing)
+    var token: Result<String, TokenProvidableError> { tokenResult }
+
+    func setToken(_ token: String) {}
+    func reset() {}
+}
+
+private struct MockRequestable: Requestable {
+    var encoding: Request.Encoding = .query
+    var httpMethod: HTTP.Method = .get
+    var endpoint: EndpointType = Endpoint.endpoint
+    var authorization: Request.Authorization
+    var contentType: String?
+}
+
+private enum Endpoint: EndpointType {
+    case endpoint
+    var path: String { "path" }
+}