GET and POST requests fail when going to my custom server - ios

I have a linux based node.js server running on BlueHost that I have configured to respond to basic GET and POST requests. I have tested these requests extensively in Postman and they all seem to work great. I figured the transition to doing these requests from an app would not be too difficult but I am currently unable to get either of them to work.
I am using boilerplate code based on this repository. As an example here is the code I am using for the get request
guard let url = URL(string: "publicIP/test") else { print("Invalid url"); return }
let session = URLSession.shared
session.dataTask(with: url) { (data, response, error) in
if let res = response {
print(res)
}
if let d = data {
print(d)
do {
let json = try JSONSerialization.jsonObject(with: d, options: [])
print(json)
} catch {
print(error)
print("ERRORED")
}
}
}.resume()
This code works great for the https://jsonplaceholder.typicode.com/users endpoint however whenever I try substituting it with my public ip (just like in Postman) and I keep getting the following error.
2018-02-18 01:14:35.633518-0800 Application[1248:321560] Task <2E64810D-C10E-4D45-82F5-9C9E37A5FE54>.<1> finished with error - code: -1002
Keep in mind this information is not passed throughout the error parameter as "ERRORED" is not printed.

Can you add this to your info.plist
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>

That error should not be related to using HTTP instead of HTTPS. App Transport Security failures return error code -1022.
The error code -1002 indicates an invalid URL. Perhaps your HTTP file contains a structurally invalid URL (e.g. missing scheme, a scheme other than http/https, etc.)?
For additional debugging, set this environment variable
CFNETWORK_DIAGNOSTICS=1
in your Xcode project and re-run the app. Once you know what URL is failing, the problem will likely become more obvious.
If it isn't, file a bug.
You can check the list of error code on below link
Apple Documentation NSURLErrorDomain Error Codes List

The issue was not any of the example code but merely a misunderstanding of what a url string should look like. I figured that I would need to match the url of the webpage as shown in the address bar of my web-browser but that is not exactly true because http does not show even if it is a part of the address in chrome.
The solution was simply to prepend http:// to the front of my url.

Related

Alamofire request fails with nil response

I am getting numerous failed requests with Alamofire 5.3, where the response object itself is nil, or the error is "cannot parse response". I can see from the server logs that all of those requests are returning valid.
Here is my setup:
API manager class:
let config = Alamofire.Session.default.session.configuration
self.session = Alamofire.Session(configuration: config, interceptor: AccessTokenInterceptor())
AccessTokenInterceptor:
class AccessTokenInterceptor: RequestInterceptor {
func adapt(_ urlRequest: URLRequest, for session: Alamofire.Session, completion: #escaping (AdapterResult<URLRequest>) -> Void) {
var adaptedRequest = urlRequest
adaptedRequest.setValue("application/json", forHTTPHeaderField: "Accept")
adaptedRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
if let token = SettingsManager.shared.userToken {
adaptedRequest.setValue("Bearer " + token, forHTTPHeaderField: "Authorization")
}
completion(.success(adaptedRequest))
}
}
This interceptor inserts my auth token from SettingsManager
I am also using the standard router for URLRequestConvertible where encoding is done by JSON serialization (dictionary) or Codable protocol (objects)
case .login(let body):
request.httpBody = try JSONSerialization.data(withJSONObject: body, options: [])
case .register(let object):
request.httpBody = try JSONEncoder().encode(object)
What is strange is that I don't think I'm doing anything different from the many other times I've used Alamofire and now the first request I make fails but the following one succeeds. If I remove the interceptor, there is no change.
If I inspect the outgoing headers or body content, it all seems normal, but the response from Alamofire is nil.
UPDATE: By using OS_ACTIVITY_MODE and iOS 13 I was able to see that it was complaining about the request headers and protocol. The server is on Elastic Beanstalk so I've been trying to mess with the SSL policy but still the first request fails every time.
This turned into quite the rabbit hole, so in the interest of community improvement, here is what I found.
After searching through the activity log errors, I noticed that iOS was complaining about an invalid header type -- upgrade. Searching for that value I found this question about removing the header. I learned that Apache acts as a proxy on Elastic Beanstalk but there is a mix up for HTTP/2 headers in the request, and iOS does not like that.
To get away from the header value, I ended up switching to Nginx proxy. Since my application uses Laravel, I then needed to deal with correcting the pretty URLs. To do that I found this answer. Now my web and mobile application both seem to be getting along nicely.

Saturn API not responding to GET when using acceptJson

The F# Saturn web framework fails on retrieving a value for GET method when acceptJson is a part of pipeline.
Below a sample code that I run to reproduce the issue:
let api = pipeline {
plug acceptJson
set_header "x-pipeline-type" "Api"
}
let apiRouter = router {
not_found_handler (setStatusCode 404 >=> text "Api 404")
pipe_through api
get "/test" (text "Hello world")
}
let appRouter = router {
forward "/api" apiRouter
}
appRouter is then added in the use_router section of the application code.
When I'm sending the request with a header Content-Type:application/json the response is "404 not found". But if I remove plug acceptJson from the api pipeline definition I get a correct response.
How to make Saturn work with the plug acceptJson?
I suspect 3615 is right - this seems similar to a problem I just solved yesterday after beating my head against the wall for a week. A request to my app (just a straight app from "dotnew new Saturn") from my browser was accepted. But a request to the same url from a test method returned a 404. It boiled down to the fact that the test request was missing an "Accept" header. When I added "Accept text/html", it worked. What I deduced from that is that, if the app can't find a content type that will be accepted according to the request, then it will report a 404. Your situation is the same - you're trying to return Json, but the request didn't include an "Accept application/json", so it can't find any page that the request would accept.
Of course, I could be wrong.

Alamofire: Download request saves error response as original file even when validation fails

I use Alamofire 4.5.1 to download some mp3 files.
If I provide incorrect URL or the request can't be authorised I get an error with 4xx status code (as it is supposed to be) and in my particular case xml with the error explanation.
The issue is that Alamofire saves the error xml response to my destination url, which looks like: .../my-sound-file.mp3
In other place in my app, which is decoupled from downloading code, I might later check if I have .../my-sound-file.mp3 on disk and try to play it, which obviously fails since my sound file is actually xml file with mp3 extension.
Is there a nicer way to prevent Alamofire saving an error data as an originally requested file?
The code I use (with my crude solution to this issue):
let destination: DownloadRequest.DownloadFileDestination = ...
let request = self.sessionManager.download(url, to: destination)
request.validate()
request.response { response in
if response.error == nil {
// do some stuff
} else {
// So far I am forced to manually remove file in case of error
try? FileManager.default.removeItem(at: destURL)
// propagate error
}
}
I stumbled upon this because I assumed that if a request validation fails the destination URL should be empty.
I think I am not the only one with this assumption: Alamofire: file download and validation failure
Personally, I delete the file in case of error. Just as you propose.

Websocket : Starscream "masked and rsv data is not currently supported"

I am developing an iOS app which required to connect with web socket server.
I can successfully connect to server but when I send request on it, it drop off the connection.
I am using Starscream library for web socket.
As per server support team:
it does not support protocol compression, but in the headers below they're requesting "permessage-deflate" from us. We'll accept uncompressed messages just fine (it's just a flag on the packet) but due to the extension they asked for, messages we send out will be compressed with that flag set.
I send request as following using Swift
let dict = ["Parameter1":"value1","Parameter2":"value2"]
do {
let data = try NSJSONSerialization.dataWithJSONObject(dict, options: NSJSONWritingOptions(rawValue: 0))
var jsonString: String = String(data: data, encoding: UInt())!
self.socket.writeString(jsonString);
} catch {
print(error)
}
It disconnect with server and print following message.
"websocket is disconnected: Optional("masked and rsv data is not currently supported")"
What the server support team meant is that the request from your WebSocket client application contained an HTTP header like below.
Sec-WebSocket-Extensions: permessage-deflate
So, if your application has a line like below, remove it.
socket.headers["Sec-WebSocket-Extensions"] = "permessage-deflate"
This error might also be thrown if the server doesn't accept the incoming connection (regardless of the reasons), or if the server crashed.
Basically, when this message shows up, the best action would be to check what is going on the server as you might be wasting time trying improve client code (it happened to me :)
For those facing this issue when trying to connect to the backend WebSocket, make sure the front end and the backend version of the socket.io are compatible. Running the following command fixed the issue for me.
pod update
Updated the both to the latest and solved the issue.
this will fix your issue I believe. just add "wamp" in the header like this.
*
var request = URLRequest(url: URL(string: URL)!)
request.setValue(["wamp"].joined(separator: ","), forHTTPHeaderField: "Sec-WebSocket-Protocol")
socket = WebSocket(request: request)
socket.delegate = self
socket.connect()

Alamofire not executing correctly in Swift

I have an Alamofire request that is suppose to download a file, but it will not execute the code it self. Here is the Alamofire Code:
var testNumbers: Int = 0
var testString: String = "Hi"
Alamofire.download(.GET, "http://www.sayweee.com/admin_groupbuy/export_deal_orders/71w4o?format=csv") { temporaryURL, response in
let fileManager = NSFileManager.defaultManager()
let directoryURL = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
let pathComponent = response.suggestedFilename
print("1")
testNumbers = 1
print(directoryURL.URLByAppendingPathComponent(pathComponent!))
print("blah")
testString = "blah"
print("2")
testNumbers = 2
return directoryURL.URLByAppendingPathComponent(pathComponent!)
}
print(testNumbers)
print(testString)
Executing this code will print this in the console:
0
Hi
I am pretty sure this means that the code within the {} are not getting executed. I've read another on this subject, and learned that Alamofire is "asynchronous", as they said in this post. I've tried to get rid of everything in viewDidLoad() method and viewDidAppear() method, and made sure I didn't have any endless loops. Even after that, the results are the same. Any ideas or suggestion on why this is happening to me? I tried to look here and on Google, but I only found one post related to this topic, the one linked above.
First of all, I put your code to run in Demo Alamofire found running results and what you said is the same, as shown in the figure below:
0
Hi
2015-12-30 14:31:29.873 iOS Example[3966:142688] App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.
According to the prompt you will see that the problem:
App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.
The solution is as follows(In the project file "info.plist" ):
In project's "info.plist" file to add a "NSAppTransportSecurity" dictionary, an element is added in the dictionary.Key for "NSAllowsArbitraryLoads", the value is: YES, make it back to the HTTP protocol for the time being.
The problem solution links:
Transport security has blocked a cleartext HTTP
The final results are as follows:
0
Hi
1
file:///Users/yangshebing/Library/Developer/CoreSimulator/Devices/151CB429-29B3-46D0-AFF5-37D5B8D9E4FC/data/Containers/Data/Application/756A32D1-64C5-48CF-B652-D3009D80780D/Documents/71w4o.html
blah
2
Specific problems you can go to query the apple official documentation, query iOS9 ATS adaptation problem.
The hope can help you!

Resources