Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions Sources/DataConnect.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class DataConnect {
private var app: FirebaseApp
private var settings: DataConnectSettings

private var grpcClient: GrpcClient
private(set) var grpcClient: GrpcClient
private var operationsManager: OperationsManager

private static var instanceStore = InstanceStore()
Expand Down Expand Up @@ -57,12 +57,12 @@ public class DataConnect {
// self.grpcClient.close
// self.operations.close

guard let projectID = app.options.projectID else {
guard app.options.projectID != nil else {
fatalError("Firebase DataConnect requires the projectID to be set in the app options")
}

grpcClient = GrpcClient(
projectId: projectID,
app: app,
settings: settings,
connectorConfig: connectorConfig,
auth: Auth.auth(app: app),
Expand All @@ -79,12 +79,12 @@ public class DataConnect {
self.settings = settings
self.connectorConfig = connectorConfig

guard let projectID = app.options.projectID else {
guard app.options.projectID != nil else {
fatalError("Firebase DataConnect requires the projectID to be set in the app options")
}

grpcClient = GrpcClient(
projectId: projectID,
app: self.app,
settings: settings,
connectorConfig: connectorConfig,
auth: Auth.auth(app: app),
Expand Down
18 changes: 14 additions & 4 deletions Sources/Internal/GrpcClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import Foundation

import FirebaseAppCheck
import FirebaseAuth
import FirebaseCoreInternal
import FirebaseCore
import GRPC
import NIOCore
import NIOHPACK
Expand All @@ -28,6 +28,8 @@ import SwiftProtobuf
actor GrpcClient: CustomStringConvertible {
nonisolated let description: String

private let app: FirebaseApp

private let projectId: String

private let threadPoolSize = 1
Expand All @@ -42,10 +44,11 @@ actor GrpcClient: CustomStringConvertible {

private let appCheck: AppCheck?

private enum RequestHeaders {
enum RequestHeaders {
static let googRequestParamsHeader = "x-goog-request-params"
static let authorizationHeader = "x-firebase-auth-token"
static let appCheckHeader = "X-Firebase-AppCheck"
static let firebaseAppId = "x-firebase-gmpid"
}

private let googRequestHeaderValue: String
Expand All @@ -69,10 +72,16 @@ actor GrpcClient: CustomStringConvertible {
}
}()

init(projectId: String, settings: DataConnectSettings, connectorConfig: ConnectorConfig,
init(app: FirebaseApp, settings: DataConnectSettings, connectorConfig: ConnectorConfig,
auth: Auth,
appCheck: AppCheck?) {
self.app = app

guard let projectId = app.options.projectID else {
fatalError("Data Connect requires a Firebase project ID to be specified.")
}
self.projectId = projectId

serverSettings = settings
self.connectorConfig = connectorConfig
self.auth = auth
Expand Down Expand Up @@ -173,10 +182,11 @@ actor GrpcClient: CustomStringConvertible {
}
}

private func createCallOptions() async -> CallOptions {
func createCallOptions() async -> CallOptions {
var headers = HPACKHeaders()

headers.add(name: RequestHeaders.googRequestParamsHeader, value: googRequestHeaderValue)
headers.add(name: RequestHeaders.firebaseAppId, value: app.options.googleAppID)

// Add Auth token if available
do {
Expand Down
53 changes: 53 additions & 0 deletions Tests/Unit/HeaderTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import FirebaseCore
@testable import FirebaseDataConnect
import Foundation
import GRPC

import XCTest

final class HeaderTests: XCTestCase {
static var defaultApp: FirebaseApp?

static var options: FirebaseOptions = {
let options = FirebaseOptions(googleAppID: "0:0000000000000:ios:testAppId",
gcmSenderID: "00000000000000000-00000000000-000000000")
options.projectID = "fdc-test"
options.apiKey = "testDummyApiKey"
return options
}()

var fakeConnectorConfigOne = ConnectorConfig(
serviceId: "dataconnect",
location: "us-central1",
connector: "kitchensink"
)

override class func setUp() {
FirebaseApp.configure(options: options)
defaultApp = FirebaseApp.app()
}

func testGmpAppIdHeader() async throws {
let dcOne = DataConnect.dataConnect(connectorConfig: fakeConnectorConfigOne)
let callOptions = await dcOne.grpcClient.createCallOptions()
let values = callOptions.customMetadata.values(
forHeader: GrpcClient.RequestHeaders.firebaseAppId, canonicalForm: false
)
let contains = values.contains { $0 == HeaderTests.defaultApp!.options.googleAppID }
XCTAssertTrue(contains)
}
}
Loading