GithubHelp home page GithubHelp logo

Comments (13)

bsneed avatar bsneed commented on May 31, 2024

This currently works as intended. The idea was before you've received results from Segment's /settings endpoint, you may have a preference for EU vs US endpoints. Segment settings has the final say, but we acknowledge this is problematic when intending to use a proxy (which I assume you're wanting to do). We'll look at this soon and try and figure out a good path forward. In the meantime feel free to fork and comment out the following line in SegmentDestination.swift

apiHost = segmentInfo?[Self.Constants.apiHost.rawValue] as? String

That'll make it such that whatever you supply will be used at all times.

from analytics-swift.

jackgene avatar jackgene commented on May 31, 2024

This currently works as intended. The idea was before you've received results from Segment's /settings endpoint, you may have a preference for EU vs US endpoints. Segment settings has the final say, but we acknowledge this is problematic when intending to use a proxy (which I assume you're wanting to do). We'll look at this soon and try and figure out a good path forward. In the meantime feel free to fork and comment out the following line in SegmentDestination.swift

apiHost = segmentInfo?[Self.Constants.apiHost.rawValue] as? String

That'll make it such that whatever you supply will be used at all times.

If this is "working as intended", can you please documented it clearly in the Analytics Swift documentation - https://segment.com/docs/connections/sources/catalog/libraries/mobile/swift-ios/

I just spent several hours last night trying to understand why our events aren't going through our proxy with the apiHost configuration set.

In fact, from my troubleshooting, it is unclear to me if what you are saying is accurate (that apiHost is being used as a default). Browsing through the source code, I do not see the apiHost value on the configuration object ever being read.

Anyway, I've opened this ticket https://segment.zendesk.com/hc/requests/488619

from analytics-swift.

jackgene avatar jackgene commented on May 31, 2024

Just to confirm, this is the workaround you are proposing, correct?
main...jackgene:analytics-swift:main

If so, it is not working for me. As I pointed out in my last comment, apiHost on the Configuration object doesn't appear to be being read at all. Let me know if I've missed anything else.

Thank you.

from analytics-swift.

bsneed avatar bsneed commented on May 31, 2024

@jackgene It is being read, I assure you. See HTTPClient.swift. That workaround is no longer necessary once this PR is merged: #165. Documentation will be updated before a point release is made.

from analytics-swift.

jackgene avatar jackgene commented on May 31, 2024

from analytics-swift.

bsneed avatar bsneed commented on May 31, 2024

@jackgene There was no "tone". I'm just sharing facts. As an employee here trying to help you, I don't appreciate yours so lets take it down a notch. See the line below as to where it's being read.

init(analytics: Analytics, apiKey: String? = nil, apiHost: String? = nil, cdnHost: String? = nil) {
self.analytics = analytics
if let apiKey = apiKey {
self.apiKey = apiKey
} else {
self.apiKey = analytics.configuration.values.writeKey
}
if let apiHost = apiHost {
self.apiHost = apiHost
} else {
self.apiHost = Self.defaultAPIHost
}
if let cdnHost = cdnHost {
self.cdnHost = cdnHost
} else {
self.cdnHost = Self.defaultCDNHost
}
self.session = Self.configuredSession(for: self.apiKey)
}

The fix has already been merged since we first spoke. A point release has yet to happen, pending documentation.

from analytics-swift.

jackgene avatar jackgene commented on May 31, 2024

@jackgene There was no "tone". I'm just sharing facts. As an employee here trying to help you, I don't appreciate yours so lets take it down a notch. See the line below as to where it's being read.

init(analytics: Analytics, apiKey: String? = nil, apiHost: String? = nil, cdnHost: String? = nil) {
self.analytics = analytics
if let apiKey = apiKey {
self.apiKey = apiKey
} else {
self.apiKey = analytics.configuration.values.writeKey
}
if let apiHost = apiHost {
self.apiHost = apiHost
} else {
self.apiHost = Self.defaultAPIHost
}
if let cdnHost = cdnHost {
self.cdnHost = cdnHost
} else {
self.cdnHost = Self.defaultCDNHost
}
self.session = Self.configuredSession(for: self.apiKey)
}

The fix has already been merged since we first spoke. A point release has yet to happen, pending documentation.

The lines you highlighted is the initializer for HTTPClient (called "constructor" in other languages). It shows that the initializer accepts an apiHost, and defaults it to nil when no value is passed in - more on initializers here - https://docs.swift.org/swift-book/LanguageGuide/Initialization.html. But the key point is these lines of code do not show apiHost being read from the Configuration object.

(Note that in Swift (and in most programming languages really), the fact that there's a constructor parameter named apiHost, and that there's a corresponding property named apiHost on the Configuration object, does not automatically bind the two)

For Configuration's apiHost to be passed to the initializer, it has to be explicitly invoked with it, it would look something like this:

let configuration = Configuration("some write key").apiHost("myhost.com/v1")
let analytics = Analytics(configuration: configuration)
HTTPClient(
  analytics: analytics,
  apiHost: configuration.values.apiHost // THIS LINE
)

If you look through the analytics-swift source, you'll find that the HTTPClient is being initialized from three different places (you can find this in Xcode by right clicking on the init function -> Find -> Find Call Hierarchy):

You'll note that in none of these locations is apiHost being set to a value read from Configuration.

Another point worth noting, you "assured me" that Configuration.Values.apiHost is being read. Here's a tip on how you can quickly see that that is not the case:

  1. Navigate to the apiHost property for Configuration.Values (https://github.com/segmentio/analytics-swift/blob/main/Sources/Segment/Configuration.swift#L34) in Xcode.
  2. Right-click on apiHost, and then Find -> Find Call Hierarchy

You'll quickly see it's not referenced anywhere. Try the same thing with say writeKey, and you'll see all the places where writeKey is being read from.

from analytics-swift.

bsneed avatar bsneed commented on May 31, 2024

Thanks for all those super useful links.

Here, I'll paste the code for you since it seems difficult for you to see it on GitHub.

    init(analytics: Analytics, apiKey: String? = nil, apiHost: String? = nil, cdnHost: String? = nil) {
        self.analytics = analytics
        
        if let apiKey = apiKey {
            self.apiKey = apiKey
        } else {
            self.apiKey = analytics.configuration.values.writeKey
        }

Low and behold, apiKey gets set from the configuration value that was specified if null was passed into the constructor. HTTPClient is a somewhat generic class that lost its way a little over time. But wait, there's more!

Just a few lines down ....

    @discardableResult
    func startBatchUpload(writeKey: String, batch: URL, completion: @escaping (_ result: Result<Bool, Error>) -> Void) -> URLSessionDataTask? {
        guard let uploadURL = segmentURL(for: apiHost, path: "/b") else {
            completion(.failure(HTTPClientErrors.failedToOpenBatch))
            return nil
        }

Enjoy.

from analytics-swift.

jackgene avatar jackgene commented on May 31, 2024

You may want to re-read this issue.

It is about apiHost not applying to the HTTPClient, NOT apiKey or writeKey.

from analytics-swift.

bsneed avatar bsneed commented on May 31, 2024

Ya got me. My apologies, apiKey has been front and center for me all week. I'll make a PR for the default setting of apiHost in the coming days, however that doesn't seem like what you needed in the first place. The linked PR has more along the lines of what you and the original poster of this bug were looking for. See Configuration.requestFactory which gives you full control over all the details of a given request (headers/url/path/etc).

from analytics-swift.

bsneed avatar bsneed commented on May 31, 2024

Actually, I'll reopen this as another issue that omits the confusion.

from analytics-swift.

jackgene avatar jackgene commented on May 31, 2024

Ya got me. My apologies, apiKey has been front and center for me all week. I'll make a PR for the default setting of apiHost in the coming days, however that doesn't seem like what you needed in the first place. The linked PR has more along the lines of what you and the original poster of this bug were looking for. See Configuration.requestFactory which gives you full control over all the details of a given request (headers/url/path/etc).

I think you are right, that the requestFactory override is more what I need.

And apologies if my frustration was coming through, but my point was that I knew I was writing the apiHost value on the Configuration object, but I wasn't seeing it have any effect.

Going through the code manually, and having Xcode try and find all references to Configuration.Values.apiHost, I find a couple of references where the value is written to, but no references where it is ever read from, hence I don't see how it could possibly be affecting any behavior of HTTPClient or anything else.

Thanks for opening the new issue, and have a nice weekend!

from analytics-swift.

bsneed avatar bsneed commented on May 31, 2024

No worries at all! Glad requestFactory does the trick for you and you're back in business. Hope you have a good weekend as well. Ttys!

from analytics-swift.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.