How to decode special characters in an NSURL in Swift? - swift

I have a string: <api address>/<parameters>?fmt=json
When I create an NSURL object from the string, the URL is: <api address>/<parameters>%3Ffmt=json
When I send the request with this URL (using an NSURLSession), however, it gets denied access, as the API wants the ? and doesn't accept %3F. How do I decode the URL to have the ? return so the API will accept the request?
UPDATE
NSURL construction
let urlRequestString = "<api url>?fmt=json&api_key=" + <key>
let apiRequestURL = NSURL(fileURLWithPath: urlRequestString)

You're using the wrong initializer, which is causing bogus results. NSURL(fileURLWithPath: urlRequestString) is intended for creating file:// URLs. It translates your URL into a format suitable for the filesystem. It's designed for file use only, so you shouldn't use it here.
If you change the initializer to be NSURL(string: urlRequestString) then your URL should be OK.

Related

URL - Found nil while unwrapping an Optional value

I'm a little ashamed to post this as I use URLs all the time but this one has me stumped!
I keep getting an 'Unexpectedly found nil while unwrapping an Optional value'
Just to add some context, I use the same format for over 20 URLs which is making requests to an API. The only difference is the ID at the end of the URL.
Ignore the insecure URL as this is simply a debug endpoint and has no bearing on the issue as I use the same URL in other calls. Also, ignore the first part of the URL, I have purposefully changed it for security purposes.
The code I use is as follows:
func returnEventParticipantsEndPoint(eventID: String) -> URLRequest {
print("URL: \(debugEndPointURL)/api​/friendgroups​/\(eventID)")
var url: URL!
url = URL(string: "\(debugEndPointURL)/api​/friendgroups​/\(eventID)")!
let requestURL = URLRequest(url: url)
return requestURL
}
The URL printed in the console (top line) before I try to return the URLRequest prints as follows:
http://blahblahblah.blah.net/api​/friendgroups​/1c8264b95884409f90b4fd8ba9d830e1
Yet, it keeps returning nil and I'd really appreciate some help with this...thanks.
The reason that it is failing is that there are hidden Unicode characters in your string. Copying and pasting the url string you provided into a hidden Unicode character checker gives the following for your url
http://blahblahblah.blah.net/apiU+200B​/friendgroups​U+200B/1c8264b95884409f90b4fd8ba9d830e1
Notice the additional hidden characters at the end of the words api and friendgroups
You can try it here https://www.soscisurvey.de/tools/view-chars.php
Have you copied and pasted the format for this? Examining the string you have some non printable Unicode characters after the words api and friendgroups. Retyping the url path and trying again worked for me

Alamofire error with JSON response

I have been struggling with Alamofire issue for days and I'm not sure if it's from the backend or the way I structure my code.
Here is the issue:
when I text my API with Postman I get the correct response if I hit the params button and add the parameters Notice the lower body is empty but the upper one is filled with parameters
However, when I use the lower parameters with the same info I get an error with no JSON. Also same error appears in Xcode when I try to call the API with the same link
this is Xcode Alamofire error
FAILURE: responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.}))
and here is Postman error
and finally this is my code to call API:
let urlStr = "api/client/meal_add"
let url = URL(string: urlStr)
let para = ["meal_id": "31",
"user_id": "2",
"qty":"2"]
let headers: HTTPHeaders = [
"Auth": "Auth" // Edited for security
]
Alamofire.request(url!, method: .post, parameters: para,encoding: URLEncoding.default, headers: headers).responseJSON { response in
print(response)
print(response.result.debugDescription)
if let value : AnyObject = response.result.value as AnyObject {
it used to work perfectly 5 days ago but I have no idea why it stoped. Also In other View Controllers I do HTTP calls to the same API and the responses have no issues, only this one.
First, I want to talk about the difference between HTTP get and post request. Get request is putting parameters in url. They are appended to the url in this format
URL?key1=value1&key2=value2
The RESTful hanlder for that URL will then parse the key value pair and use them. When you click on the param button in your postman, it actuall doing this append param to url thing. However this get into problem when you have lots of param. Usually, an url will have some problem if it exceeds length 8000. So a post request is actually nesting the parameters inside the request, not on the url. So normally in a post request, you will only see the URL, not the ?key1=value1&key2=value2 part.
Back to your problem, I have no idea how your server side handles this post request with parameters in url but since an empty post request with param in url works, in your swift code, you can simply append the param in your url and do a post request with no parameters.
let urlStr = "api/client/meal_add?meal_id=31&user_id=2&qty=2"
let url = URL(string: urlStr)
Alamofire.request(url!, method: .post, parameters: [],encoding: URLEncoding.default, headers: headers).responseJSON { response in
Moving forward, I strongly recommand you to have a look at your server side to make sure your post request is written in the correct way

Multipart form-data file uploading using Alamofire

I have looked at questions like this or that one but it is still not working.
Also I have a question about what should I enter into fileURL param from function multipartFormData.appendBodyPart?
Should it be a way to image from PC, or image must be added to Images.xcassets? What should I send here?
It looks like you have three issues that you need to fix.
Use .POST instead of POST.
The fileURL needs to be a valid NSURL that points to a file on the file system. You cannot just use the filename.
You are using the responseString serializer, but named the third parameter in the closure JSON. Then you are letting result into s and trying to print it out. The result parameter doesn't even exist anywhere. Instead, you should print(JSON).
Hopefully that helps clear things up a bit.
Try to use .POST not POST
As an alternative solution upload an encoded file and send it as a parameter of POST.
// `data` is NSData
let base64String = data!.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.allZeros)
let parameters = ["image_data": base64String] as [String: AnyObject]
Alamofire.request(.POST, "http://your-url.com", parameters: parameters)
The cons of this method is that the data will get %33 larger due to encoding. If you have bandwidth problems it may not be a good solution.

Decode REST Url in Objective-C

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];

NSURL parameterString with .NET service call

I'm tring to use the NSURL class's parameterString message to return the string from the following url:
http://www.host.com/Api/Service.svc/GetStuff?param=thisIsTheParamValue
I keep getting nil for the parameterString. Does that url not conform to the standards that Apple uses?
The URL doesn't conform to the standard NSURL uses for parameterString. NSURL uses RFC 1808 standard, which defines the parameter string as ";" params. Use the query message instead to get the string after the '?'.