3

Is there a way to find out what port number a NSURLRequest will use to satisfy a particular NSURL?

Obviously, I could hard code port 80 for http request and port 443 for https requests. But surely there's a built-in way to get the port number from a URL scheme in Cocoa Touch.

The port method on NSURL only returns a value when the port is specified in the URL. It'll work for http://stackoverflow.com:80, but not the more common http://stackoverflow.com.

The context here is that I'm signing into a web service that's redirecting me(Say, from (http://webservice.invalid/path/to/api to http://webservice2.invalid:2003/path/to/api). All URLs are based on the service's base URL, which I want to update to reflect reality and avoid future redirects.

At the moment, I'm extracting the scheme and host, but hadn't considered that the port might change as well. I don't want to specify the port on future requests if I didn't get a port as part of the redirect.

User97693321
  • 3,336
  • 7
  • 45
  • 69
Steven Fisher
  • 44,462
  • 20
  • 138
  • 192

2 Answers2

2

Don't hardcode the ports. Use getservent() instead.

blarf
  • 101
  • 2
  • I'm not looking fort the services running on the client, but which port to connect to on a server (in an environment where I need to specify the port). – Steven Fisher Aug 11 '14 at 15:40
  • @StevenFisher `getservent()` and `getservbyname(const char *, const char *)` have nothing to do with services running on the client. Per the `getservent()` man page, they parse the [`services(5)`](https://developer.apple.com/library/mac/documentation/Darwin/Reference/Manpages/man5/services.5.html) file. – blarf Aug 12 '14 at 00:53
  • Promising. I'll look into this. Thanks. – Steven Fisher Aug 12 '14 at 15:00
2

NSURLRequest has a method called URL which returns an NSURL which has a method called port.

NSURLRequest request = ...;

NSNumber *port = [[request URL] port];
NSLog(@"Port: %d", [port intValue]);

Documentation:

port
Returns the port number of a URL conforming to RFC 1808.

- (NSNumber *)port
Return Value The port number of the URL. If the receiver does not conform to RFC 1808, returns nil.

EDIT:

If the port is not set in the URL and you know the scheme, there is nothing wrong with hardcoding the default port. E.g. http = 80, https = 443, ftp = 21. These ports are defined in the standard and you can just store them in a constant somewhere in your code to avoid magic numbers.

Community
  • 1
  • 1
Joe
  • 56,979
  • 9
  • 128
  • 135
  • 1
    This doesn't work: the port returned is nil if the port is not provided with the URL. That's not the default port for a scheme, only the port provided in the URL. – Steven Fisher Oct 05 '11 at 19:55
  • I should have explicitly said the port was not part of the URL in the initial question. I've updated it. – Steven Fisher Oct 05 '11 at 19:58
  • Ok what do you need the port for? The defaults ports are going to be what they use by default according to RFC 1808 so you could hard code them if necessary. – Joe Oct 05 '11 at 19:58
  • Yeah, I'm hard coding them now. It just seems inelegant to do string compares on the scheme in my application code, when Foundation does the same thing. As for what I'm using it for, I'll go update the question again. :) – Steven Fisher Oct 05 '11 at 19:59
  • Just looked through some Apple code looks like they hard code as well. Search the source for [CFFTPStream.c](http://opensource.apple.com/source/CFNetwork/CFNetwork-129.9/FTP/CFFTPStream.c) for `port = 21;` I think you will be safe hardcoding the default port for a standard. – Joe Oct 05 '11 at 20:18