iOS app calling redirected domain - ios

I'm creating rest based app and when I make requests to server url:
Example : 107.XXX.XXX.XXX:8080/taxi - it`s working, returns me JSON.
But when I make request to domain forwarded to that ip my app shows me that exception:
2017-04-18 20:23:53.063 Project X[4121:301275] http://107.XXX.XXX.XXX:8080/taxi
2017-04-18 20:23:53.065 Project X[4121:301275] fireGetWebserviceCall finally
2017-04-18 20:23:53.252 Project X[4121:301275] Error: Error Domain=com.alamofire.error.serialization.response Code=-1011 "Request failed: not found (404)" UserInfo={NSUnderlyingError=0x600000240600 {Error Domain=com.alamofire.error.serialization.response Code=-1016 "Request failed: unacceptable content-type: text/html" UserInfo={com.alamofire.serialization.response.error.response= { URL: http://107.XXX.XXX.XXX:8080/taxi } { status code: 404, headers {
"Content-Language" = en;
"Content-Length" = 977;
"Content-Type" = "text/html;charset=utf-8";
Date = "Tue, 18 Apr 2017 17:23:51 GMT";
Server = "Apache-Coyote/1.1";
} }
When I paste that URL into a browser I get normal JSON response.
Can someone explain to me why returned info is text/html and how to fix it?

I use the code below to ensure that I get JSON responses back from URLs:
Swift
var request = URLRequest(url: self.url!)
request.httpMethod = self.httpMethod
request.httpBody = body
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")

Related

MessageExtension returned a NSURLErrorDomain when requesting the server

I'm developing iOS message extension to filter the unwanted message. The plugin needs a help from server to filter the message. However, the iOS returned the error NSURLErrorDomain while requesting the server.
Based on the official document, I have done the following steps:
I added Associated Domains capability with value: messagefilter:mydomain.io
I defined the key/value pair in Info.plist of Message Extension.
ILMessageFilterExtensionNetworkURL has value: https://mydomain.io/api/v1/sms
The code that I test the request as follows:
let url = URL(string: "https://mydomain.io/api/v1/sms")!
var request = URLRequest(url: url)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("you-value-goes-here", forHTTPHeaderField: "X-API-KEY")
let task = URLSession.shared.dataTask(with: request) { data, _, error in
if let data = data {
print(data)
} else if let error = error {
print("Http failed: \(error)")
}
}
task.resume()
From the stack trace, as far as I known, there is a problem with dns resolution. Why does this happened and how to fix this case?
[0] (null) "_kCFStreamErrorCodeKey" : Int32(-72000)
[1] (null) "NSUnderlyingError" : domain: "kCFErrorDomainCFNetwork" - code: 18446744073709550613
[2] (null) "_NSURLErrorFailingURLSessionTaskErrorKey" : "LocalDataTask <B496A974-7009-4FCE-BF45-FEC07BA1E8DF>.<1>"
[3] (null) "_NSURLErrorRelatedURLSessionTaskErrorKey" : 1 element
[4] (null) "NSLocalizedDescription" : "A server with the specified hostname could not be found."
Thanks

Alamofire and Digest-Auth

I am trying to implement in my Apps Digest-auth but i am struggling, or is not working properly.
I have setup my request as you describe in your AuthenticationTestCase and looks like the following code:
let userName = "***********"
let password = "***********"
let qop = "auth"
let xmlStr: String = "<?xml version=\"1.0\" encoding=\"utf-8\"?><methodCall><methodName>authenticate.login</methodName></methodCall>"
let postData:Data = xmlStr.data(using: String.Encoding.utf8, allowLossyConversion: true)!
let url = URL(string: "https://app.**********.co.uk/service/mobile/digest-auth/\(qop)/\(userName)/\(password)")
var request = URLRequest(url: url!)
request.httpShouldHandleCookies = true
request.setValue("\(String(describing: xmlStr))", forHTTPHeaderField: "Content-Length")
request.setValue("application/xml", forHTTPHeaderField: "Content-Type")
request.setValue("IOS133928234892nil", forHTTPHeaderField: "User-Agent")
request.setValue("application/xml", forHTTPHeaderField: "Accept")
request.httpMethod = "POST"
request.httpBody = postData
AF.request(request)
.authenticate(username: userName, password: password)
.response { response in ........
When I run the above code, I am receiving the following response from the remote server:
Response XML Error:
You must be authenticated to access this resource
Response Error Code: 401
Response Headers:
Optional([AnyHashable("X-Powered-By"): PHP/7.1.33, AnyHashable("Pragma"): no-cache, AnyHashable("Content-Length"): 310, AnyHashable("Date"): Fri, 22 May 2020 09:15:48 GMT, AnyHashable("Server"): Apache/2.4.41 () OpenSSL/1.0.2k-fips PHP/7.1.33, AnyHashable("Cache-Control"): no-store, no-cache, must-revalidate, AnyHashable("Content-Type"): Content-Type: application/xml, AnyHashable("Www-Authenticate"): Digest realm="Mobile",nonce="31JEmMdeSVfXWQ:OT/ndHY6ch/PjqFwA6uutg",opaque="c81e728d9d4c2f636f067f89cc14864c",qop="auth",algorithm="MD5", Digest realm="Mobile",nonce="31JEmMdeSVfXWQ:OT/ndHY6ch/PjqFwA6uutg",opaque="c81e728d9d4c2f636f067f89cc14864c",qop="auth",algorithm="SHA-512-256", Digest realm="Mobile",nonce="31JEmMdeSVfXWQ:OT/ndHY6ch/PjqFwA6uutg",opaque="c81e728d9d4c2f636f067f89cc14864c",qop="auth",algorithm="SHA-256", AnyHashable("Connection"): Keep-Alive, AnyHashable("Keep-Alive"): timeout=5, max=100, AnyHashable("Expires"): Thu, 19 Nov 1981 08:52:00 GMT])
Note: If I do the same request via Postman, it works properly.
It looks like the Alamofire is not properly handling the Digest challenge.
Please could you help me on this issue?

Swift/iOS URL request to Node.js API endpoint

I have standard code in Swift like below:
private func testFormUrlEncodedRequest() {
let headers = [
"Content-Type": "application/x-www-form-urlencoded",
"Accept": "application/json"
]
let postData = NSMutableData(data: "user_id=5874ae8ae9a98c2d6cef1da8".data(using: String.Encoding.utf8)!)
postData.append("&offset=0".data(using: String.Encoding.utf8)!)
postData.append("&limit=20".data(using: String.Encoding.utf8)!)
let request = NSMutableURLRequest(url: NSURL(string: "http://www.example.com/endpoint")! as URL,
cachePolicy: .useProtocolCachePolicy,
timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data
ViewController.log(request: request as! URLRequest)
print((request as URLRequest).curlString)
let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
ViewController.log(data: data, response: response as? HTTPURLResponse, error: error)
if (error != nil) {
print(error)
} else {
let httpResponse = response as? HTTPURLResponse
print(httpResponse)
}
})
dataTask.resume()
}
But the problem is that it hangs on, and then request times out with error.
REST API is written in Node.js and gets error in body-parser module like request aborted.
I can make successfully the same request with POSTMAN or curl (from Terminal) and I get correct response.
Code on server which I have no access to seems to be also rather standard, and was used in previous projects where it was tested to work correctly with iOS apps.
I have no idea why this request goes ok with POSTMAN and doesn't work with URLSession in Swift.
Any help will be beneficial.
Here is error message printed to console I am getting:
Optional(Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo={NSUnderlyingError=0x6000013196e0
{Error Domain=kCFErrorDomainCFNetwork Code=-1001 "(null)" UserInfo={_kCFStreamErrorCodeKey=-2102, _kCFStreamErrorDomainKey=4}},
NSErrorFailingURLStringKey=http://example.com/api/endpoint, NSErrorFailingURLKey=http://example.com/api/endpoint,
_kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-2102, NSLocalizedDescription=The request timed out.})
This request gives error in such cases:
1. form-url-encoded params in HTTP request body
2. raw application/json params in HTTP request body
3. It works if params are passed in query params
4. It crashes with request aborted error on server side (body-parser module)
5. node.js uses standard app.use()
// support parsing of application/json type post data
app.use(bodyParser.json());
//support parsing of application/x-www-form-urlencoded post data
app.use(bodyParser.urlencoded({ extended: true }));
It uses http without SSL but in Info.plist there is App Transport Security > Allow Arbitrary Loads set to YES etc.
UPDATE:
This is error on server side
BadRequestError: request aborted
at IncomingMessage.onAborted (/Users/michzio/Click5Interactive/Reusable Parts/NetworkApi/node_modules/raw-body/index.js:231:10)
at emitNone (events.js:86:13)
at IncomingMessage.emit (events.js:188:7)
at abortIncoming (_http_server.js:381:9)
at socketOnClose (_http_server.js:375:3)
at emitOne (events.js:101:20)
at Socket.emit (events.js:191:7)
at TCP.Socket._destroy.cb._handle.close [as _onclose] (net.js:510:12)
Node.js Test Code:
const express = require('express');
const port = 9001;
const app = express();
const bodyParser = require('body-parser');
var todos = [{id:1, title:'buy the milk'}, {id:2, title:'rent a car'}, {id:3, title:'feed the cat'}];
var count = todos.length;
app.use(bodyParser.urlencoded({ extended: true }))
app.use(bodyParser.json());
app.get('/test', (request, response) => {
console.log("-----")
console.log(request.params);
console.log(request.body);
console.log(request.query);
console.log("-----")
response.status(200).json( todos );
});
app.listen(port);
It seems that GET + query params works, and POST + body params (url-from-encoded or application/json) also works correctly.
So it doesn't work for GET body params url-form encoded and GET body params application/json. Is it some limitation of URLSession/URLRequest in Swift. POSTMAN can pass params in body with GET and server receives it in request.body !
UPDATE 2!
Yes, it seems that in Android/Kotlin with OkHttpClient there even is not possible to define Request Body with GET method. And there is also this error. Maybe this only works with POSTMAN and curl, and should not be used in real application scenario to join GET and body params.
public fun makeNetworkRequest(v: View) {
object : Thread() {
override fun run() {
val client = OkHttpClient()
val mediaType = MediaType.parse("application/json")
val body = RequestBody.create(mediaType, "{ \"test\" : \"nowy\", \"test2\" : \"lol\" }")
/*
val request = Request.Builder()
.url("http://10.0.2.2:9001/test")
.get()
.addHeader("Content-Type", "application/json")
.build()
*/
val mySearchUrl = HttpUrl.Builder()
.scheme("http")
.host("10.0.2.2")
.port(9001)
.addPathSegment("test")
.addQueryParameter("q", "polar bears")
.build()
val request = Request.Builder()
.url(mySearchUrl)
.addHeader("Accept", "application/json")
.method("GET", body)
.build()
val response = client.newCall(request).execute()
Log.d("RESPONSE", response.toString())
}
}.start()
}

Alamofire post method in iOS Swift 4?

For getting push notification here i am sending postitem, token, like count and currentname using alamofire post method(pod version alamofire 4.5). I did not get any response when post method called and it does not show any errors.
I tried keeping breaking points in alamofire function, it call alamofire.requestion then it goes out function.
Here is the code tried to send post method to backend:
func postNotification(postItem: String, post: Post) {
print("Get token from post:::",post.token)
print(postItem)
let token = UserDefaults.standard.string(forKey: "token")
let headers: HTTPHeaders = ["Content-Type" :"application/x-www-form-urlencoded"]
let parameters : [String:Any] = ["count":post.likeCount!, "likedby":currentName, "postId=":postItem, "token": post.token!]
Alamofire.request("http://highavenue.co:9000/likesnotification/", method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: nil).responseJSON { (response:DataResponse<Any>) in
switch(response.result) {
case .success(_):
if let data = response.result.value{
print(data)
}
break
case .failure(_):
print(response.result.error as Any)
break
}
}
}
Getting console error like this
2018-07-10 14:21:07.980212+0530 HighAvenue[10584:4236493] Task <B5FC98AB-C3FE-
4D4F-9A93-72D3FFE35DF7>.<1> finished with error - code: -1001
Optional(Error Domain=NSURLErrorDomain Code=-1001 "The request timed out."
UserInfo={NSUnderlyingError=0x1c0e478f0 {Error Domain=kCFErrorDomainCFNetwork Code=-1001 "(null)" UserInfo={_kCFStreamErrorCodeKey=-2102, _kCFStreamErrorDomainKey=4}}, NSErrorFailingURLStringKey=http://highavenue.co:9000/likesnotification/, NSErrorFailingURLKey=http://highavenue.co:9000/likesnotification/, _kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-2102, NSLocalizedDescription=The request timed out.})
That is because you are not setting request time in your network call, by default your request time is a small interval, so please increase request timeout time. something like this,
let request = NSMutableURLRequest(url: URL(string: "")!)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.timeoutInterval = 120 // 120 secs
let values = ["key": "value"]
request.httpBody = try! JSONSerialization.data(withJSONObject: values, options: [])
Alamofire.request(request as! URLRequestConvertible).responseJSON {
response in
// do whatever you want here
}
Second mistake in your code is you are trying to access http url which are by default are not allowed so you have to by pass this security from your app, Please refer to this answer in order to remove this security layer from your app.
The resource could not be loaded because the App Transport Security policy requires the use of a secure connection

How to set Content-Type in AFNetworking?

I want to set "application/x-www-form-urlencoded" with post method
So ,I set request.requestSerializer.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") But When I set the request to the server the Content-Type is not change what happen?
this is error
{com.alamofire.serialization.response.error.response=<NSHTTPURLResponse: 0x7c166450> { URL: http://test.com } { status code: 404, headers {
Connection = "keep-alive";
"Content-Length" = 434;
"Content-Type" = "text/html";
Date = "Mon, 13 Jul 2015 11:18:18 GMT";
Server = "nginx/1.0.15";
} }, NSErrorFailingURLKey=http://text.com, NSLocalizedDescription=Request failed: not found (404),
this is my code:
var request = AFHTTPRequestOperationManager();
request.requestSerializer = AFHTTPRequestSerializer()
request.requestSerializer.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.POST(url, parameters: parameters, success: { (oper,obj) -> Void in
// do something
}) { (oper, error) -> Void in
// do something with error
}
It's exactly what the error says: your server is sending back a webpage (HTML) for a 400 status code, when you were expecting JSON.
A 400 status code is used a bad request, which is probably generated because you're sending URL-form-encoded text as application/json. What you really want is to use AFJSONRequestSerializer for your request serializer.
manager.requestSerializer = [AFJSONRequestSerializer serializer];
I am not doing any code of AFNetworking in Swift so I can't tell you code of that but you can get idea from objective-c code.
I hope it will help you.

Resources