I am getting this error when trying to connect to an API in flutter to get user data. The API is remote, the phone has connection to the internet, I'm using an android phone to build the APP.
this is the error.
[ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: SocketException: OS Error: Connection refused, errno = 111, address = address, port = 43798
for back end we are using PHP Laravel , but the API should be open to anyone who has the address at this point in development, so much so that the get request works both in Postman and in browser when calling.
As for the flutter function, this is the code being used.
Future<User> getUser(url) async {
print("here");
var params = {
"id": "01142",
};
Uri uri =
Uri.parse(url);
uri.replace(queryParameters: params);
final response = await http.get(
uri,
headers: <String, String>{
'Content-Type': 'application/json',
'Accept': "*/*",
'connection': 'keep-alive',
'Accept-Encoding': 'gzip, deflate, br',
'host': 'ipv4',
},
);
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
user = User.fromJson(jsonDecode(response.body));
print("NEW USER");
print(user);
return user;
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load user');
}
}
According to back end Laravel isnt using SSL either, what might be the problem?
Related
I am trying to make a request to a PHP server from my swift app. For some reason php is showing an empty array as the $_REQUEST variable. I have looked through stack overflow and implemented everything I can find that might help, but still getting an empty array in php. Here is the relevant swift code...
func connect(_ pin: String, completion: #escaping(Result<ConnectResponse?, Error>) -> ()) {
let params: [String : Any] = [
"mobile_pin_connect": pin,
"device_info": UIDevice().model,
"additional_info": UIDevice().systemVersion
]
doRequest(params: params) { (data) in
if let data = data {
do {
let res = try JSONDecoder().decode(Dictionary<String, String>.self, from: data)
completion(.success(
ConnectResponse(success: (res["success"] == "true"), connect_id: res["connect_id"] ?? nil, error: res["error"] ?? nil)))
} catch {
completion(.failure(error))
}
} else {
print("in else block")
}
}
}
fileprivate func doRequest(params: [String: Any], completion: #escaping (Data?) -> ()) {
let body = createJsonBody(params)!
self.request.httpBody = body
print("Sending request with thw following variables")
print(String(data: body, encoding: .utf8)!)
print(String(data: self.request.httpBody!, encoding: .utf8))
URLSession.shared.dataTask(with: self.request) { (data, response, error) in
if let error = error {
print("Error in request: \(error)")
completion(nil)
}
let stringResult = String(data: data!, encoding: .utf8)!
let properResult = String(stringResult.map {
$0 == "." ? "=" : $0
})
let decodedData = Data(base64Encoded: properResult)
completion(decodedData)
}.resume()
}
fileprivate func createJsonBody(_ params: [String: Any]) -> Data? {
do {
let jsonData = try JSONSerialization.data(withJSONObject: params)
let body = Data(jsonData).base64EncodedData()
return body
} catch {
print("Unable to create json body: " + error.localizedDescription, error)
return nil
}
}
That sends the request to the server, the setup for the request is in the static var setup...
private static var sharedConnector: ApiConnector = {
let url = URL(string: "https://mywebsiteURLhere.com/api/mobile/challenge")
var request = URLRequest(url: url!)
request.httpMethod = "POST"
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
let connector = ApiConnector(request)
return connector
}()
So I have the right header values for application/json I have the request method set to post, I am base64encoding the json data and in PHP I have the setup getting php://input...
$rawRequest = file_get_contents("php://input");
and dumping the $_REQUEST variable to an error log, but I always get array\n(\n)\n
it is just showing an empty array
I even did
error_log("Raw request from index.php");
error_log(print_r($rawRequest, true));
and it logs a completely empty line.
I can't figure out why PHP is getting nothing in the request, from everything I have seen online I am doing the request correctly in swift. Any help is really appreciated. Thank you
As per your Swift Code, Can you please replace the following method.
fileprivate func createJsonBody(_ params: [String: Any]) -> Data? {
do {
let jsonData = try JSONSerialization.data(withJSONObject: params)
let body = Data(jsonData)
return body
} catch {
print("Unable to create json body: " + error.localizedDescription, error)
return nil
}
}
You need to replace this line let body = Data(jsonData) with
let body = Data(jsonData).base64EncodedData()
Without seeing your PHP code, it is difficult to determine the entire picture. However, whatever steps you perform to encode your data via the client (Swift) you must reverse to successfully decode the message on the server.
For example, if you prepare and send the request from your client as follows.
Client:
JSON encode data
base-64 encode
send data
The your server must reverse the steps to successfully decode the data.
Server:
recv data
base-64 decode data
JSON decode data
Unless your server requires it, I would remove the base-64 encode step, as it only complicates your encode / decode process.
I have created a working example: https://github.com/stuartcarnie/stackoverflow/tree/master/q59329179
Clone it or pull down the specific code in your own project.
To test, open up a terminal and run the php server:
$ cd q59329179/php
$ php -S localhost:8080 router.php
PHP 7.3.9 Development Server started at Thu Dec 19 10:47:58 2019
Listening on http://localhost:8080
Document root is /Users/stuartcarnie/projects/stackoverflow/q59329179/php
Press Ctrl-C to quit.
Test it works with curl in another terminal session:
$ curl -XPOST localhost:8080 --data-binary '{"string": "foo", "number": 5}'
Note you should see output in the php session:
[Thu Dec 19 11:33:43 2019] Array
(
[string] => foo
[number] => 5
)
Run the Swift test:
$ cd q59329179/swift
$ swift run request
Note again, decoded output in php session:
[Thu Dec 19 11:20:49 2019] Array
(
[string] => string value
[number] => 12345
[bool] =>
)
Your request is probably not arriving through the POST structure, but is kept in the request body.
Try running this as your first PHP operation:
$raw = file_get_contents('php://input');
and see what, if anything, is now into $raw. You should see a Base64 encoded string there, that you need to decode - like this, if you need an array:
$info = json_decode(base64_decode($raw), true);
I've tested your code and it's working fine. The issue might be at your PHP end. I've tested the following code on local server as well as on httpbin
The output from a local server (recent version of XAMPP (php 7.3.12)):
Sending request with thw following variables
eyJhZGRpdGlvbmFsX2luZm8iOiIxMy4yLjIiLCJtb2JpbGVfcGluX2Nvbm5lY3QiOiIxMjM0IiwiZGV2aWNlX2luZm8iOiJpUGhvbmUifQ==
result eyJhZGRpdGlvbmFsX2luZm8iOiIxMy4yLjIiLCJtb2JpbGVfcGluX2Nvbm5lY3QiOiIxMjM0IiwiZGV2aWNlX2luZm8iOiJpUGhvbmUifQ==
message ["additional_info": "13.2.2", "mobile_pin_connect": "1234", "device_info": "iPhone"]
Code:
ApiConnector.swift
import Foundation
import UIKit
class ApiConnector{
var request: URLRequest
private init(request: URLRequest) {
self.request = request
}
public static var sharedConnector: ApiConnector = {
let url = URL(string: "http://localhost/post/index.php")
var request = URLRequest(url: url!)
request.httpMethod = "POST"
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
let connector = ApiConnector(request: request)
return connector
}()
func connect(_ pin: String, completion: #escaping(Result<Dictionary<String, String>, Error>) -> ()) {
let params: [String : Any] = [
"mobile_pin_connect": pin,
"device_info": UIDevice().model,
"additional_info": UIDevice().systemVersion
]
doRequest(params: params) { (data) in
if let data = data {
do {
let res = try JSONDecoder().decode(Dictionary<String, String>.self, from: data)
completion(.success(res))
} catch {
completion(.failure(error))
}
} else {
print("in else block")
}
}
}
fileprivate func doRequest(params: [String: Any], completion: #escaping (Data?) -> ()) {
let body = createJsonBody(params)!
self.request.httpBody = body
print("Sending request with thw following variables")
print(String(data: body, encoding: .utf8)!)
URLSession.shared.dataTask(with: self.request) { (data, response, error) in
if let error = error {
print("Error in request: \(error)")
completion(nil)
}
let stringResult = String(data: data!, encoding: .utf8)!
print("result \(stringResult)")
let properResult = String(stringResult.map {
$0 == "." ? "=" : $0
})
let decodedData = Data(base64Encoded: properResult)
completion(decodedData)
}.resume()
}
fileprivate func createJsonBody(_ params: [String: Any]) -> Data? {
do {
let jsonData = try JSONSerialization.data(withJSONObject: params)
let body = Data(jsonData).base64EncodedData()
return body
} catch {
print("Unable to create json body: " + error.localizedDescription, error)
return nil
}
}
}
ViewController.swift
import UIKit
class ViewController: UIViewController {
let session = URLSession.shared
override func viewDidLoad() {
super.viewDidLoad()
ApiConnector.sharedConnector.connect("1234") { (result) in
switch result {
case .success(let message):
print("message \(message)")
case .failure(let error):
print(error.localizedDescription)
}
}
}
}
index.php
echo file_get_contents("php://input");
You can verify your code by doing a request to https://httpbin.org/post
output:
Sending request with thw following variables
eyJkZXZpY2VfaW5mbyI6ImlQaG9uZSIsImFkZGl0aW9uYWxfaW5mbyI6IjEzLjIuMiIsIm1vYmlsZV9waW5fY29ubmVjdCI6IjEyMzQifQ==
result {
"args": {},
"data": "eyJkZXZpY2VfaW5mbyI6ImlQaG9uZSIsImFkZGl0aW9uYWxfaW5mbyI6IjEzLjIuMiIsIm1vYmlsZV9waW5fY29ubmVjdCI6IjEyMzQifQ==",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "en-us",
"Content-Length": "108",
"Content-Type": "application/json; charset=utf-8",
"Host": "httpbin.org",
"User-Agent": "SessionTest/1 CFNetwork/1120 Darwin/19.0.0"
},
"json": null,
"origin": "122.173.135.243, 122.173.135.243",
"url": "https://httpbin.org/post"
}
in else block
If you are running an older version of PHP then You might need HTTP_RAW_POST_DATA
Have look at this SO for more info on PHP side.
I am trying to upload image using below function everything working fine only is i want to send image in post and when i am trying get image getting nothing
This is for call API
Future getUploadImg(access_token,File _image) async {
print("Image: $_image");
String apiUrl = '$_apiUrl/user/upload-profile-image';
final length = await _image.length();
final request = new http.MultipartRequest('POST', Uri.parse(apiUrl));
request.headers['Accesstoken'] = "Bearer $access_token";
request.files.add(new http.MultipartFile('imagefile',_image.openRead(), length));
http.Response response = await http.Response.fromStream(await request.send());
print("Result: ${response.body}");
return json.decode(response.body);
}
My file that is passing to server is:
File: '/storage/emulated/0/Android/data/com.dotsquares.ecomhybrid/files/Pictures/c5df03f7-097d-47ca-a3c5-f896b2a38c086982492957343724084.jpg'
I got the result finally we need to pass string for image sharing my working code if anyone need for help:
Future getUploadImg(access_token,File _image) async {
print("Image: $_image");
var result;
var stream = new http.ByteStream(DelegatingStream.typed(_image.openRead()));
var length = await _image.length();
var uri = Uri.parse('$_apiUrl/user/upload-profile-image');
var request = new http.MultipartRequest("POST", uri);
request.headers['Accesstoken'] = "Bearer $access_token";
var multipartFile = new http.MultipartFile('imagefile', stream, length, filename: basename(_image.path));
request.files.add(multipartFile);
var response = await request.send();
print(" ===================response code ${response.statusCode}");
await response.stream.transform(utf8.decoder).listen((value) {
print(" =====================response value $value");
result = value;
});
return json.decode(result);
}
To avoid the following problems:
write failed
connection closed before ...
Flutter Doctor Error - SocketException: Write failed (OS Error: Broken pipe, errno = 32)
you need to add the correct parameters in the headers.
In my case, these problems occur with uploading images and sending base64 encoded requests. I solved it by adding the following 'connection' header: 'keep-alive':
final response = await this.httpClient.put(
url,
encoding: Utf8Codec(),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
'Accept': "*/*",
'connection': 'keep-alive',
'Accept-Encoding' : 'gzip, deflate, br',
},
body: body,
);
I'm currently working with Stripe, trying to send a Stripe token to my backend using Alamofire and Heroku. My code is as follows:
func postStripeToken(_ token: STPToken) {
let URL = "https://limitless-fjord-73001.herokuapp.com/charge.php"
let params = ["stripeToken": token.tokenId,
"amount": Int(self.amountTextField.text!)!,
"currency": "usd"] as [String : Any]
Alamofire.request(URL, method: .post, parameters: params)
.responseJSON { response in
print(response.request as Any) // original URL request
print(response.response as Any) // URL response
print(response.data as Any) // server data
print(response.result as Any) // result of response serialization
if let JSON = response.result.value {
print("JSON: \(JSON)")
}
}
}
The problem I'm having is that my response.result is printing as FAILURE (see Line 13 above). Everything else seems to be printing fine, including the token and the lines response.request, response.response, and response.data:
Optional(https://limitless-fjord-73001.herokuapp.com/charge.php)
Optional(<NSHTTPURLResponse: 0x600000425400> { URL: https://limitless-fjord-73001.herokuapp.com/charge.php } { status code: 500, headers {
Connection = "keep-alive";
"Content-Length" = 0;
"Content-Type" = "text/html; charset=UTF-8";
Date = "Mon, 29 May 2017 05:58:35 GMT";
Server = Apache;
Via = "1.1 vegur";
} })
Optional(0 bytes)
FAILURE
Any ideas on why I may be getting a failure? Thanks!
It is hard to tell what the problem is from the little you've shown us :)
However, this line:
Optional(<NSHTTPURLResponse: 0x600000425400> { URL: https://limitless-fjord-73001.herokuapp.com/charge.php } { status code: 500, headers {
And more specific this part of the line:
status code: 500, headers
Seems to indicate that you received an error code 500 from your backend, meaning that there was a server side error of some sort.
So, is there a log file somewhere on your server that you could look at and see if it tells you something?
Hope that gives you something to work with.
I configured my app:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
let pushSettings: UIUserNotificationSettings = UIUserNotificationSettings(
forTypes:[.Alert, .Badge, .Sound],
categories: nil)
UIApplication.sharedApplication().registerUserNotificationSettings(pushSettings)
UIApplication.sharedApplication().registerForRemoteNotifications()
return true
}
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
print("My token is: \(deviceToken)");
}
// Failed to register for Push
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
print("Failed to get token; error: %#", error) //Log an error for debugging purposes, user doesn't need to know
}
Copy my device token, to my python script:
import time
from apns import APNs, Frame, Payload
apns = APNs(use_sandbox=True, cert_file='NodesDownCert.pem', key_file='NodesDownKey.pem')
# Send a notification
token_hex = 'xxx'
payload = Payload(alert="Hello World!", sound="default")
apns.gateway_server.send_notification(token_hex, payload)
I ran script, it didn't return errors, but i haven't received notifications at my Ipad. I tried php script from this tutorial, script returns "Message successfully delivered", but i'm still not receive any message. Php code here.
Any ideas how to debug or what is wrong ?
I am trying to connect to my localhost API (that I need to build along with the iOS swift app) that returns a json string. The API is written in Laravel 4 framework.
Here is the iOS Swift code to connect and receive the code:
func checkEmail() {
var request = NSMutableURLRequest(URL: NSURL(string: "http://localhost:3306/laravel/rojectapi/checkEmail"))
var session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
var params = ["email":"myemail#me.com", "password":"password"] as Dictionary
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &err)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
println("Response: \(response)")
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Body: \(strData)")
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as NSDictionary
println("hey")
if(err) {
println(err!.localizedDescription)
}
else {
var success = json["success"] as? Int
println("Success: \(success)")
}
})
task.resume()
}
The Laravel PHP Route:
Route::post('/checkEmail', array(
'as' => 'checkEmail',
'uses' => 'FrontEndController#checkEmail'
));
And then the front-end-controller with the checkEmail method:
public function checkEmail() {
$validator = Validator::make(Input::all(), array(
'email' => 'required|unique:users|email'
));
if($validator->fails()) {
return $validator->messages()->toJson();
} else {
return Response::json(array('success' => true));
}
}
Am I not connecting to the server correctly? I need to do so on my iPhone 5s connected to my laptop, as well as in the emulator. I have tried name.local, localhost:<post> and name.local:<post> in the URL.
Update
I got the code from this tutorial
Either pass NSJSONReadingAllowFragments (.AllowFragments in Swift) or format your JSON properly.
A simple google search revealed that error 3840 is caused due to improperly formatted JSON being passed to the iOS JSON parser.
This occurs if the API is expecting some data from you and you are not able to send it or it is not being received by the APi, try to Echo out the parameter which are received by the API as a response to your iOS Request, It may also occur if you APi Implementation has some error in it, though you may be able to see this error in your Web Console.
I have this error, when i add languages to Localizations in project. When i add language, must change from "localizable strings" to "interface builder storyboard". I mean project of iOS app. Could help you.