I'm out of my depth.

I'm trying to make a URL GET request to a service I'm discovering via Bonjour.

I have gotten a NWBrowser.Result, and I've gotten an NWEndpoint.

The endpoint is an IPv6 link local address.

How the hell do I make a URLRequest to this? I don't seem to be able to construct a URL from what I've got, but I suspect I'm holding it wrong.

Again, this is probably simple, but I'm way out of my depth here.

Wait, it seems the presence of “%en0" at the end may be the problem?

I can construct the URL without that, but actually connecting to that server with URLSession doesn't work.

(Worth noting it's HTTP not HTTPS; could ATS be stomping on me? If so, how would I know?)

Whoops. I didn't think of that. @_nd_ pointed out I need to percent-escape… the percent sign. That got me over the finish line. 🎉

https://fnordon.de/@_nd_/110881126508440982

Andreas Hartl (@[email protected])

@[email protected] my reading of https://datatracker.ietf.org/doc/html/rfc6874 is that you must percent-escape the %: http://[<IPv6address>%25<zoneID>]

Fnordon
@caseyliss @_nd_ This is classic case of the internet being awesome. There is almost always someone that not only knows the answer to your problem, but is also willing to share it.
@chrishuck @caseyliss @_nd_ As long as you have the reach for it to be seen of course. I think posting a question like this and expecting an accurate response wouldn’t work for the majority of social media users. (I’m not trying to bemoan anyone the visibility/notoriety they have earned, just pointing out that while this is a great result, it likely wouldn’t be the same for most other people.)
@chrishuck @caseyliss @_nd_ I knew the answer but I’m 11 hours behind reading my feed. RFC6874 explains how zone identifiers are represented in the authority component of a URL https://www.rfc-editor.org/rfc/rfc6874
RFC 6874: Representing IPv6 Zone Identifiers in Address Literals and Uniform Resource Identifiers

@caseyliss @_nd_ “escape the percent sign” sounds like something from a self help book
@caseyliss whyyyy is there a reference to the NIC? 🧐🤔
@atlauren @caseyliss That’s because all interfaces have an fe80:: address. So you need to let it know which interface that particular host is on
Link local is a special case. Each segment of the network has its own independent link local space. Link locals also all share a prefix, fe80::/10. When you have interfaces connected to different segments they will be physically separated while seemingly within the same address space. Regular prefix-based routing doesn’t work. Instead, a “zone index” is added to differentiate each segment. Unix-like systems use the NIC name as an index (the standard requires just a number too)
@caseyliss the “%en0” should only be needed for link-local addresses. All other address types should not need it.
@jgjl It is link local
@caseyliss without the interface id the OS cannot determine which interface to use, since the link local prefix is the same on all interfaces. Hence, it makes sense that you don’t get a connection without it.
@jgjl Okay, fair enough. But now I need to construct a URL from it so I can issue a HTTP request
@caseyliss If you can do the Http get in Safari with the url then I would think it HAS to be the Http call instead of HTTPS and the App Transport Security.

@caseyliss my reading of https://datatracker.ietf.org/doc/html/rfc6874 is that you must percent-escape the %:

http://[<IPv6address>%25<zoneID>]

RFC 6874: Representing IPv6 Zone Identifiers in Address Literals and Uniform Resource Identifiers

This document describes how the zone identifier of an IPv6 scoped address, defined as <zone_id> in the IPv6 Scoped Address Architecture (RFC 4007), can be represented in a literal IPv6 address and in a Uniform Resource Identifier that includes such a literal address. It updates the URI Generic Syntax specification (RFC 3986) accordingly.

IETF Datatracker
@_nd_ nailed it. Thank you!!!

@caseyliss Not an expert on IPv6, but in general for running on iOS devices you'll need the “Privacy - Local Network Usage Description” and the ATS setting to allow insecure requests to (that or all) domains. For the second reason you should get an error message. For the first not so much

From experience, I would also recommend testing on the final device (assuming an iPhone for example) because the Network framework can behave differently in small but meaningful ways depending on the platform.

@caseyliss In a browser you would enter an IPV6 address like this: https://[XXXXXIPV6ADDRESS]/index.html

Obviously replace XXXXXIPV6ADDRESS with your IPV6 address. Notice the [] in the URL.

@gc_headtech Tried that. Didn't work.

(Again, VERY likely I'm holding it wrong)

@caseyliss Does it work in safari?
@caseyliss also foudn this: https://developer.apple.com/forums/thread/711196 It appears that this should work in 16.
"According to RFC 2732 Section 2, IPv6 addresses must be enclosed in [ and ] when it’s part of an URL. In this particular case, the host should be ipv6URLComponents.host = “[2001:0000:3238:dfe1:0063:0000:0000:fefb]”.”
URLComponent does not accept IPv6 … | Apple Developer Forums

@gc_headtech you have to do that? I guess I’ve never seen an IPv6 address in a URL before. Didn’t know that.
@caseyliss does the device you are connecting from have an IPv6 address?
@caseyliss can’t you just resolve the bonjour signal to get an ip and port, then make the request on thr endpoint with what we swift provides for http requests?
@maddox I did. It’s IPV6 link local. Which URL doesn’t understand
@caseyliss turn off ipv6 on your router. Like the solution has been for 20 years 😂
@maddox in summary this is all your fault.
@caseyliss is the link local endpoint the _only_ endpoint that is returned?
@lindvall as far as I can tell, yes; the ATV definitely has an ipv4 address though.
@caseyliss I am going to guess that this is Bonjour's fault simply because nothing that uses Bonjour has ever been reliable. I'm guessing that nothing that uses Bonjour can be made to be reliable. Simply using both wifi and Ethernet on the same device seems to completely destroy it.
@caseyliss is it a NWEndpoint.hostPort? Are you advertising it or is it another app you are working with? You can set the required local endpoint to be 127.0.0.1 (or maybe even a Unix socket but who knows if that works)

@maxtown yes, it’s hostPort.

Trying to consume another app’s services.

@caseyliss huh that sucks. If you pass it into getaddrinfo do you get another address that does work with URLRequest? Like 127.0.0.1?

https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/getaddrinfo.3.html

Mac OS X Manual Page For getaddrinfo(3)

HTML versions of the iOS man pages.

@caseyliss are you not getting an mDNS hostname?
@caseyliss at one point in my life escape sequences were the bane of my existence. I’m now retired and my own escape sequence.

@caseyliss they still call it bonjour? I thought that was one of the ‘features’ they touted then forgot about 25 years ago.

But that ‘bump to share contacts’ iOS feature was around iPhone 4 iPhone 6 days too, and they are touting that as a new iOS 17 feature.

For a successful company, Apple sure does seem to forget a lot, has a right hand not knowing what the left hand is doing vibe.

@caseyliss Strictly speaking, you're discouraged from resolving the address out of an NWEndpoint yourself; it can change. You open an NWConnection with the NWEndpoint directly and it resolves the address internally.

https://developer.apple.com/forums/thread/122638

But how you make an HTTP request over an NWConnection, I do not know. Different network layers.

Get IP & Port from NWBrowser | Apple Developer Forums