Skip to content

Commit

Permalink
Using dedicated session for feeds, centralised auth header creation.
Browse files Browse the repository at this point in the history
  • Loading branch information
erikdoe committed Feb 11, 2024
1 parent c4c01fc commit ec369ab
Show file tree
Hide file tree
Showing 10 changed files with 102 additions and 6 deletions.
12 changes: 12 additions & 0 deletions CCMenu.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@
2FA28718B9A6BD8E1C32FF55 /* CCTrayResponseParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FA28075764358E9D929CECD /* CCTrayResponseParserTests.swift */; };
2FA28FBCC0398D63EF2D2C16 /* NSImageExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FA28CB152CE8C0CFD6EE3A8 /* NSImageExtensionTests.swift */; };
3C4DEDA22B49AB7A00B85A8C /* NSWorkspaceExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C4DEDA12B49AB7A00B85A8C /* NSWorkspaceExtension.swift */; };
3CB911D52B7142A0009DF781 /* URLSessionExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CB911D42B7142A0009DF781 /* URLSessionExtension.swift */; };
3CB911D72B78E891009DF781 /* URLRequestExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CB911D62B78E891009DF781 /* URLRequestExtension.swift */; };
3CB911D92B78EB3F009DF781 /* URLRequestExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CB911D82B78EB3F009DF781 /* URLRequestExtensionTests.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -169,6 +172,9 @@
2FA2833D541ABE8B0D2E7615 /* GitHubResponseParserTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GitHubResponseParserTests.swift; sourceTree = "<group>"; };
2FA28CB152CE8C0CFD6EE3A8 /* NSImageExtensionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSImageExtensionTests.swift; sourceTree = "<group>"; };
3C4DEDA12B49AB7A00B85A8C /* NSWorkspaceExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSWorkspaceExtension.swift; sourceTree = "<group>"; };
3CB911D42B7142A0009DF781 /* URLSessionExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLSessionExtension.swift; sourceTree = "<group>"; };
3CB911D62B78E891009DF781 /* URLRequestExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLRequestExtension.swift; sourceTree = "<group>"; };
3CB911D82B78EB3F009DF781 /* URLRequestExtensionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLRequestExtensionTests.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -285,6 +291,7 @@
2FA2833D541ABE8B0D2E7615 /* GitHubResponseParserTests.swift */,
0362EBEE2B5313120079DEFE /* NotificationFactoryTests.swift */,
03F9B88F297C6EEC00FA866E /* CompactRelativeFormatStyleTests.swift */,
3CB911D82B78EB3F009DF781 /* URLRequestExtensionTests.swift */,
2FA28CB152CE8C0CFD6EE3A8 /* NSImageExtensionTests.swift */,
03BD7EA02598E57A000F9495 /* Info.plist */,
);
Expand Down Expand Up @@ -379,6 +386,8 @@
isa = PBXGroup;
children = (
03F9B88D297C5D5B00FA866E /* CompactRelativeFormatStyle.swift */,
3CB911D62B78E891009DF781 /* URLRequestExtension.swift */,
3CB911D42B7142A0009DF781 /* URLSessionExtension.swift */,
037AB214297334EE00C33589 /* UserDefaultsExtension.swift */,
03DD697D2B646E3800D7AD9D /* NSColorExtensions.swift */,
03BD7EF9259A180C000F9495 /* NSImageExtension.swift */,
Expand Down Expand Up @@ -593,6 +602,7 @@
0331F39F29A8155000245956 /* MenuExtraViewModel.swift in Sources */,
03F9B894297D38AA00FA866E /* Pipeline.Status.swift in Sources */,
3C4DEDA22B49AB7A00B85A8C /* NSWorkspaceExtension.swift in Sources */,
3CB911D52B7142A0009DF781 /* URLSessionExtension.swift in Sources */,
03BD7E892598E579000F9495 /* AppDelegate.swift in Sources */,
037AB21A297B1DCD00C33589 /* MenuBarExtraLabel.swift in Sources */,
0336DBAE2984903B00E5811C /* AddGitHubPipelineSheet.swift in Sources */,
Expand All @@ -607,6 +617,7 @@
03F9B898297D4D8F00FA866E /* MenuItemViewModel.swift in Sources */,
03D4BB05265EE6B50023F4CB /* GitHubResponseParser.swift in Sources */,
03CC11F02652F70800130833 /* CCTrayFeedReader.swift in Sources */,
3CB911D72B78E891009DF781 /* URLRequestExtension.swift in Sources */,
0336DBAC29848FE200E5811C /* AddCCTrayPipelineSheet.swift in Sources */,
0329F89E25B0F0F10043FAB1 /* AppearanceSettings.swift in Sources */,
03DD697C2B61A26900D7AD9D /* CCTrayPipelineBuilder.swift in Sources */,
Expand All @@ -631,6 +642,7 @@
2FA2827139B00E15C5CD2E7F /* GitHubResponseParserTests.swift in Sources */,
03B263F42B509E5300CA989A /* StatusChangeTests.swift in Sources */,
03B1D75F2A6079CD007BCB8A /* MenuItemModelTests.swift in Sources */,
3CB911D92B78EB3F009DF781 /* URLRequestExtensionTests.swift in Sources */,
03F9B89A297D930A00FA866E /* CCTrayFeedReaderTests.swift in Sources */,
0362EBEF2B5313120079DEFE /* NotificationFactoryTests.swift in Sources */,
03B1D7632A6085F1007BCB8A /* PipelineRowModelTests.swift in Sources */,
Expand Down
25 changes: 25 additions & 0 deletions CCMenu/Source/Miscellaneous/URLRequestExtension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright (c) Erik Doernenburg and contributors
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use these files except in compliance with the License.
*/

import Foundation

extension URLRequest {

public static func basicAuthValue(user: String, password: String) -> String {
let credentialString = "\(user):\(password)"
guard let credentialData = credentialString.data(using: .utf8) else {
// TODO: Consider adding error handling here
return ""
}
let credentialAsBase64 = credentialData.base64EncodedString(options: [])
return "Basic \(credentialAsBase64)"
}

public static func bearerAuthValue(token: String) -> String {
return "Bearer \(token)"
}

}
41 changes: 41 additions & 0 deletions CCMenu/Source/Miscellaneous/URLSessionExtension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright (c) Erik Doernenburg and contributors
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use these files except in compliance with the License.
*/

import AppKit

extension URLSession {

public static var feedSession = makeFeedSession()

private static func makeFeedSession() -> URLSession {
let session = URLSession(configuration: URLSessionConfiguration.default, delegate: FeedSessionDelegate(), delegateQueue: nil)

return session
}
}

class FeedSessionDelegate: NSObject, URLSessionTaskDelegate {

func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping @Sendable (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {

let authMethod = challenge.protectionSpace.authenticationMethod
guard authMethod == NSURLAuthenticationMethodHTTPBasic else {
completionHandler(.performDefaultHandling, nil)
return
}

// TODO: figure out what to do if we end up here
// We should only end up here if we didn't provide credentials but the server requires
// authentication or if the credentials provided are not accepted. Note: Realistically
// this is the only place to discover the authentication realm the server uses, should
// we need to expose that to the user.

debugPrint("received authentication challenge for \(challenge.protectionSpace)")
completionHandler(.performDefaultHandling, nil)
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class CCTrayProjectList: ObservableObject {
}

func fetchProjects(request: URLRequest) async throws -> [CCTrayProject] {
let (data, response) = try await URLSession.shared.data(for: request)
let (data, response) = try await URLSession.feedSession.data(for: request)
guard let response = response as? HTTPURLResponse else {
throw URLError(.unsupportedURL)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class GitHubRepositoryList: ObservableObject {

private func fetchRepositories(request: URLRequest) async -> [GitHubRepository] {
do {
let (data, response) = try await URLSession.shared.data(for: request)
let (data, response) = try await URLSession.feedSession.data(for: request)
guard let response = response as? HTTPURLResponse else {
throw URLError(.unsupportedURL)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class GitHubWorkflowList: ObservableObject {

private func fetchWorkflows(request: URLRequest) async -> [GitHubWorkflow] {
do {
let (data, response) = try await URLSession.shared.data(for: request)
let (data, response) = try await URLSession.feedSession.data(for: request)
guard let response = response as? HTTPURLResponse else {
throw URLError(.unsupportedURL)
}
Expand Down
2 changes: 1 addition & 1 deletion CCMenu/Source/Server Monitor/CCTrayFeedReader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class CCTrayFeedReader {

private func fetchStatus(request: URLRequest) async {
do {
let (data, response) = try await URLSession.shared.data(for: request)
let (data, response) = try await URLSession.feedSession.data(for: request)
guard let response = response as? HTTPURLResponse else {
throw URLError(.unsupportedURL)
}
Expand Down
2 changes: 1 addition & 1 deletion CCMenu/Source/Server Monitor/GitHubAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class GitHubAPI {
request.addValue("application/vnd.github+json", forHTTPHeaderField: "Accept")
request.addValue("2022-11-28", forHTTPHeaderField: "X-GitHub-Api-Version")
if let token, !token.isEmpty {
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
request.setValue(URLRequest.bearerAuthValue(token: token), forHTTPHeaderField: "Authorization")
}
return request
}
Expand Down
2 changes: 1 addition & 1 deletion CCMenu/Source/Server Monitor/GitHubFeedReader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class GitHubFeedReader {

private func fetchStatus(request: URLRequest) async -> (Pipeline.Status?, String?) {
do {
let (data, response) = try await URLSession.shared.data(for: request)
let (data, response) = try await URLSession.feedSession.data(for: request)
guard let response = response as? HTTPURLResponse else {
throw URLError(.unsupportedURL)
}
Expand Down
18 changes: 18 additions & 0 deletions CCMenuTests/URLRequestExtensionTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright (c) Erik Doernenburg and contributors
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use these files except in compliance with the License.
*/

import XCTest
@testable import CCMenu

class URLRequestExtensionTests: XCTestCase {

func testCreatesUnicodeBasicAuthHeader() throws {
let value = URLRequest.basicAuthValue(user: "test", password: "\u{1F600}")
XCTAssertEqual("Basic dGVzdDrwn5iA", value)
}

}

0 comments on commit ec369ab

Please sign in to comment.