Decode REST Url in Objective-C - iphone

I'm creating a module that receive and REST URL and need to match a pattern and extract the parameters
For example:
the URL "http://Product/1" should match the pattern "http://Product/{productId:long}"
and return the Dictionary with productId as a key and "1" as the value in as long
Does anyone knows about a Framework for IPhone that does it, or at least some of it?

NSURL has a method pathComponents, which returns an array with all the different path components. That should help you get the integer part. To get the name I'd use the host method of the NSURL. The docs say, that it should work if the URL is properly formatted, might as well give it a try then.
All in all, no need to convert into a string, there seems to be plenty of methods to work out the components of the URL from the NSURL object itself.

NSString *path = [[#"path+with+spaces"
stringByReplacingOccurrencesOfString:#"+" withString:#" "]
stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

Related

iOs application fails to open a file associated with the application (swift) [duplicate]

I've seen many questions on SO concerning converting between NSURL and NSString. They all involve using either NSString *path = [myURL absoluteString]; or NSString *path = [myURL path];. What is the actual difference between these methods? Is there a time when one should be used over the other? I tried consulting the Apple Docs, but I found it less than helpful.
I'm used to URL's only being mentioned in discussions concerning websites and other topics regarding sending information between different machines, and never being mentioned when dealing with just the file structure on a single machine. Perhaps this is where some of my confusion is coming from, since NSURL seems to be the preferred way of accessing files, regardless of whether that file exists on a network or on the local device. Or maybe that's a totally unrelated topic. I'm not even sure.
Question 1:
What is the actual difference between these methods?
Let's analyze this writing 6 lines of code - 3 for a local and 3 for http URL - and playing around with them a little bit.
Let's create an NSURL using the file:// scheme. If you ask yourself why there are 3 / after file: you should remember that a complete URL exists of a scheme (file:// and absolute or relative path (you can find more information on creating URLs in RFC 1808 on page 3). We use an absolute path which starts with a / so that we end up with ///.
NSURL *aLocalURL = [NSURL URLWithString:#"file:///Users/dennis/Desktop/"];
NSLog(#"absolute string: %#", aLocalURL.absoluteString);
NSLog(#"path: %#", aLocalURL.path);
Output:
absolute string: file:///Users/dennis/Desktop/
path: /Users/dennis/Desktop
So we see that absoluteString still knows its scheme whereas path doesn't have this information anymore.
Note: path is a file (directory) URL and as the docs state, the trailing slash it is stripped.
Now let's take a look at remote URLs. With these type of URLs most people are more familiar. We create it using the same procedure as for local URLs. Our scheme is now http:// and our path is www.apple.com/.
NSURL *anHTTPURL = [NSURL URLWithString:#"http://www.apple.com/"];
NSLog(#"absolute string: %#", anHTTPURL.absoluteString);
NSLog(#"path: %#", anHTTPURL.path);
Output:
absolute string: http://www.apple.com/
path: /
Again, we see that the absolute string still knows its scheme but path is now /. So path seems to be not an appropriate way when working with remote URLs.
However, when we have an URL like http://www.apple.com/index.html we get
absolute string: http://www.apple.com/index.html
path: /index.html
Reading the docs helps here, too:
Per RFC 3986, the leading slash after the authority (host name and port) portion is treated as part of the path.
So the path is everything beginning (and including) at the slash after the authority which is www.apple.com in our case.
Question 2
Is there a time when one should be used over the other?
From the docs: (method: path)
If this URL object contains a file URL (as determined with isFileURL), the return value of this method is suitable for input into methods of NSFileManager or NSPathUtilities.
In my opinion that sentence states clearly that you should use path when you work with NSFileManager or NSPathUtilities.
Conclusion:
When you work with remote URLs you (generally) use absoluteString, otherwise the result is not what you (generally) want.
When you work with local URLs use path.
Sources:
http://www.ietf.org/rfc/rfc1808.txt
http://www.ietf.org/rfc/rfc3986.txt
NSURL Class Reference
Adding to HAS' response -- the Apple docs mention that Path-based URLs are simpler in some ways, however file reference URLs have the advantage that the reference remains valid if the file is moved or renamed while your app is running.
From the documentation for "Accessing Files and Directories":
"Path-based URLs are easier to manipulate, easier to debug, and are generally preferred by classes such as NSFileManager. An advantage of file reference URLs is that they are less fragile than path-based URLs while your app is running. If the user moves a file in the Finder, any path-based URLs that refer to the file immediately become invalid and must be updated to the new path. However, as long as the file moved to another location on the same disk, its unique ID does not change and any file reference URLs remain valid."
https://developer.apple.com/library/content/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/AccessingFilesandDirectories/AccessingFilesandDirectories.html
One further note, and I've only tried this for Swift and URL not NSURL. The relativeTo form of URL:
URL(fileURLWithPath: aPath, relativeTo: URL)
generates a URL that behaves not fully like a remote URL (as in #HAS above) and not like a file URL.
So, for example:
let url0 = URL(fileURLWithPath: "/Foo")
let url1 = URL(fileURLWithPath: "Bar", relativeTo: url0)
print("\(url1.path)")
// Output: "/Bar\n"
(similar to results for a remote URL, but not a file URL).
If we use absoluteString, we get:
print("\(url1.absoluteString)")
// Output: "file:///Bar\n"
(not similar to either a file URL or a remote URL).

API call returning different results based on whitespace encoding (%2520 vs. %20)

I just switched from ASIHTTPRequest to AFNetworking.
My app allows a user to enter a search term, and then I make an api call to my server (rails) to retrieve a list of relevant objects to display on the phone. Simple enough.
Too Long, Won't Read
With the ASI library, the search term sent to the server would be something like st%20helena. Now, with the AFNetworking, my search term sent to the server is st%2520helena. Oddly enough, this is actually making a difference. With %20, I receive no results. With %2520, I receive the results I was expecting.
My question is, why does this make a difference? I know that %2520 is an encoded '%' + 20, which equals a whitespace character, which in my mind should be identical to passing %20.
Details
Before, I was simply appending the search term to the URL after first encoding it:
NSString *encoded = [#"st helena" stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *url = [NSString stringWithFormat:#"http://www.example.com/?=%#, encoded];
Now, with AFNetworking, I'm passing an NSDictionary to the parameters argument of AFHTTPClient#getPath.
NSString *encoded = [#"st helena" stringByAddingPercentEscapesUsingEncoding:NSUTR8StringEncoding];
NSDictionary *dict = #{ #"q" : encoded };
[[myClient sharedClient] getPath:#"" parameters:dict ...]
Since AFNetworking encodes items in the dictionary, my search string is being double encoded, which is why the % of '%20' is being converted into '%25'.
My question is, why does this make a difference? I know that %2520 is an encoded '%' + 20, which equals a whitespace character, which in my mind should be identical to passing %20.
No, they aren't identical. The parsing code isn't supposed to just keep decoding over and over again until there aren't any more percent signs left. If that were the case, it would be impossible to transmit the actual percent character. It's only supposed to decode it once. This means that if %2520 goes over the wire, it is decoded into the data %20 and processing stops there. If %20 goes over the wire, it is decoded once into a space. The decoding is only supposed to happen once. If your web service is treating %2520 as a space, then it has a double-decoding bug.

I wanna put an xml file content into a URL, can I?

NSURL *url = [NSURL URLWithString:#"appName://<?xml version=\"1.0\" encoding=\"UTF-8\"?>"];
But the url = nil. I found if I remove the "<" and ">" signs, it will be ok.
So, the two signs cannot be used in a URL? Should I replace the signs with another one?
Thanks!
I solved this problem.
Before I do NSURL *url = [NSURL URLWithString:#"...."];
I first do:
NSString *urlStr = [string stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
And when parse this url on the receiver side, I firstly do:
NSString *urlString = [[url absoluteString] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; // url is a NSURL
Why would you not just POST the document in the body of the request?
GET requests are not designed for this. You may get into difficulty if there are UTF-8 chars in the document.
Also What is the maximum length of a URL in different browsers? implies a max of 2083 chars.
You're into a very browser/proxy dependent scenario.
Theoretically yes. You can use urlEncode to do this.
The HTTP protocol does not place any limit on the length of the URL.
RFC says:
Note: Servers ought to be cautious about depending on URI lengths
above 255 bytes, because some older client or proxy implementations
might not properly support these lengths.

objective c http query

Hey, Iam new to objective c and really dont know much about it. I have been given a query that is gonna I need to send data in to the server.Query is like this http://abc.com/insertipademail.php?name=name&email=email I need to enter the name and email I have constructed the string But I dont know how to send it to the server. Can someone help me out please. Or point me in the right direction. Thanks
For starters, take a look a NSString's stringWithContentsOfURL:encoding:error: method. You could do something like:
// NSString * myURLString = whatever you do to build the url
NSURL * myURL = [NSURL URLWithString: myURLString];
NSString * response = [NSString stringWithContentsOfURL: myURL encoding: NSUTF8StringEncoding error: NULL];
NSLog(#"The response was: %#", response);
As written, this will ignore all errors and perform the request synchronously. In a real app, you probably want to handle any error that occur, and perhaps perform the request in the background. See the URL Loading System Programming Guide for further documentation. You can also try using any of several open source libraries such as those suggested in David M.'s answer.
I like the library ASIHTTPRequest. There is also HTTPRiot.

How to uniquely identify nsmangedobject with string?

I'm using Core data and region monitoring. The only way to distinguish between monitored regions is with a NSString for identifier. I'd love to use NSManagedObjectID, but I can't get it to work.
What I've tried:
NSURL *objURL = [managedObjectID URIRepresentation];
NSError *err;
NSString *identifier = [NSString stringWithContentsOfURL:myURL
encoding:NSASCIIStringEncoding
error:&err];
the error I get is:
The operation couldn’t be completed. (Cocoa error 256.)
Any ideas of a better way? Or what I'm doing wrong?
You should not get the contents of the URI of the NSManagedObjectID. stringWithContentsOfURL:encoding:error: tries to load the resource pointed by the URI; it uses appropriate operations depending whether the URI is http or file or etc. But it doesn't know how to deal with an NSManagedObjectID URI, and it's not what you want to do anyway.
Instead, I guess what you want to do is
NSString*identifier=[objURL absoluteString];
This gives a string representation of the URL.
I'll add Marcus's comment so that everyone will notice:
Be aware that the objectID can and does change, especially when a migration occurs. Do not rely on that value to be consistent between one launch of the application and the next.