Trying to make a request with http in Flutter - flutter

I am trying to make a class in Flutter that can send requests to an API and then store the response inside the class, however every time I send a request I get some sort of infinite request that end up in timing out. Here is my code:
When the user press the button in the screen:
onPressed: () async {
print('Email: ${emailFieldController.text} and password: ${passwordFieldController.text}');
await Api.sendRequest('POST', '/session', {
"email": emailFieldController.text,
"password": passwordFieldController.text
});
if (Api.content.containsKey("error")) {
print("Error connectiong with API");
print("The error was:" + Api.content["error"].toString());
} else {
if (Api.content["status"] == 200) {
print("User find");
} else {
print("User not find");
}
}
})
The class that I built:
import 'dart:convert';
import 'package:http/http.dart';
class Api {
static final String baseURL = 'http://192.168.15.4/api/v1';
static Map content;
static Future<void> sendRequest(String method, String endpoint, [Map body, Map headers]) async {
Response response;
switch (method) {
case 'GET':
try {
response = await get('$baseURL' + endpoint);
Api.content = jsonDecode(response.body);
} catch (e) {
Api.content["error"] = e.toString();
}
break;
case 'POST':
try {
response =
await post('$baseURL' + endpoint, body: body, headers: headers);
Api.content = jsonDecode(response.body);
print('Passando depois POST');
} catch (e) {
Api.content["error"] = e.toString();
}
break;
case 'PUT':
try {
response =
await put('$baseURL' + endpoint, body: body, headers: headers);
Api.content = jsonDecode(response.body);
} catch (e) {
Api.content["error"] = e.toString();
}
break;
case 'DELETE':
try {
response = await delete('$baseURL' + endpoint, headers: headers);
Api.content = jsonDecode(response.body);
} catch (e) {
Api.content["error"] = e.toString();
}
break;
}
}
}
I also tried to alter the return type of the method, but got the same result.

So I discovered what was wrong, baseURL attribute was missing the port, so the request never found it's target. So in the and the baseURL value was: http://192.168.15.4:3333/api/v1

Related

Flutter: How to send multiple images using for loop

I am using http package to perform multipart request.I am trying to upload multiple images using for loop but I am not getting any idea how to do it following is my postman response in the below image you can see 2 fields one is attribute and another one is image here I want to loop only adhar and pan inside attributes after sending "mobileno":"4567654","role":"p","userstatus":"D", to database
following is my multipart request code
Future<void> insertCategory(String category, BuildContext context) async {
var flutterFunctions =
Provider.of<FlutterFunctions>(context, listen: false);
var data = {"mobileno":"4567654","role":"p","userstatus":"D","adhar":"adhar","pan":"pan"};
var url = PurohitApi().baseUrl + PurohitApi().insertcategory;
Map<String, String> obj = {"attributes": json.encode(data).toString()};
try {
loading();
final client = RetryClient(
http.Client(),
retries: 4,
when: (reponse) {
return reponse.statusCode == 401 ? true : false;
},
onRetry: (request, response, retryCount) async {
if (retryCount == 0 && response?.statusCode == 401) {
var accesstoken = await Provider.of<Auth>(context, listen: false)
.restoreAccessToken();
request.headers['Authorization'] = accesstoken;
print(accesstoken);
}
},
);
var response = await http.MultipartRequest('Post', Uri.parse(url))
..files.add(await http.MultipartFile.fromPath(
"imagefile", flutterFunctions.imageFile!.path,
contentType: MediaType("image", "jpg")))
..headers['Authorization'] = token!
..fields.addAll(obj);
final send = await client.send(response);
final res = await http.Response.fromStream(send);
var messages = json.decode(res.body);
loading();
print(messages);
} catch (e) {
print(e);
}
}
Future<Object> addUserImages(List<XFile> files, String userID, String token) async {
try {
var url = Uri.parse(API_BASE_URL + addUserImagesUrl);
var request = http.MultipartRequest("POST", url);
request.headers['Authorization'] = "Bearer ${StaticServices.userBaseModel!.token!.token}";
for (var i = 0; i < files.length; i++) {
String fileName = DateTime.now().microsecondsSinceEpoch.toString().characters.takeLast(7).toString();
var pic = http.MultipartFile.fromBytes("files", await File(files[i].path).readAsBytes(), filename: '${userID}_${i}_$fileName', contentType: MediaType("image", files[i].mimeType ?? "png"));
//add multipart to request
request.files.add(pic);
}
var response = await request.send();
var responseData = await response.stream.toBytes();
var responseString = String.fromCharCodes(responseData);
if (response.statusCode == 200) {
return Success(response: Images.fromJson(jsonDecode(responseString)));
}
return Failure(
errorMessage: responseString,
);
} on HttpException {
return Failure(errorMessage: "No Internet Connection");
} on FormatException {
return Failure(errorMessage: "Invalid Format");
} on SocketException {
return Failure(errorMessage: "No Internet Connection");
} catch (e) {
return Failure(errorMessage: "Invalid Error");
}
}

GET api in flutter failing with I/flutter ( 4017): {code: 404, message: HTTP 404 Not Found}

My requirement is need to make get rest api call in flutter.my code is as below
final url = "https://app2.sas.com/uh/device/1890/publicKey";
https://app2.sas.com/ is my base url followed by api end point
should i need to add any certificate for https://app2.sas.com/ to work?
void getPublickey() async {
print('getPublickey');
try {
final response = await http.get(Uri.parse(url));
final jsonData = jsonDecode(response.body);
if (response.statusCode == 200) {
print(jsonData.toString());
} else {}
} catch (err) {
print(err.toString());
}
}
when i hit above api i m getting below response, please let me know any mistake i m doing above?
I/flutter ( 4017): {code: 404, message: HTTP 404 Not Found}
Any help is appreciated
try
Future <void>
instead of void and remove http
Future getPublickey() async {
print('getPublickey');
try {
final response = await get(Uri.parse(url));
final jsonData = jsonDecode(response.body);
if (response.statusCode == 200) {
print(jsonData.toString());
} else {}
} catch (err) {
print(err.toString());
}
}
I don't think the problem is from Flutter. Trying out your URL https://app2.sas.com/uh/device/1890/publicKey returns a 404 too.
You should double-check the URL and make sure the endpoint is correct.
You should probably be returning the string public key:
Future getPublickey() async {
print('getPublickey');
try {
final response = await http.get(Uri.parse(url));
final jsonData = jsonDecode(response.body);
if (response.statusCode == 200) {
print(jsonData.toString());
return jsonData;
} else {
print(response.statusCode);
return null;
}
} catch (err) {
print(err.toString());
return null;
}
}

How to refresh token and retry request on 401 error using Flutter

I try to refresh token and retry request on 401 error, but can not understand how to do it by right way
This is a recreation from what I remember so there can be typo and small errors maybe.
I hope you get an idea what I am trying to do here.
import 'package:http/http.dart' as http;
class APIUtility {
Uri uri;
String path, method;
var body;
var headers;
APIUtility({ #required this.path, #required this.method, this.body}) {
this.uri = Uri.parse("http://localhost:4000/api/${this.path}");
this.headers = {'Content-Type': 'application/json'};
}
Future request({ bool useToken = true }) async {
http.Response response;
if ( useToken ) { this.header['token'] = await getAccessToken(); }
try {
response = await // call api with http package with correct path, method and body
if ( useToken && response.statusCode == 401 ) return await _refreshTokenAndRequest();
else return jsonDecode(response.data);
}
catch (e) {
print(e);
return null;
}
}
_refreshTokenAndRequest() async {
String accessToken = await getAccessToken();
String refreshToken = await getRefreshToken();
var body = {'access_token': accessToken, 'refresh_token': refreshToken};
http.Response response = await http.post("${this.baseUrl}/api/auth/refresh", body: body);
if (response.statusCode == 200 || response.statusCode == 201) {
saveAccessToken(response.body['access_token']);
saveRefreshToken(response.body['refresh_token']);
return await request();
} else {
// Logout user from app
// Delete all database, token and all user info and show login screen;
return null;
}
}
}

HttpException occure when i post a request to a server as below

This method is to post an order to a server and it's in a Provider class :
Future<void> addOrder(OrderRequest orderRequest) async {
final prefs = await SharedPreferences.getInstance();
String accessToken = prefs.getString(Constants.prefsUserAccessTokenKey);
String url = Urls.addOrderUrl;
try {
var bodyParams = json.encode({
"Branch": {"Id": orderRequest.branchId},
"DeliveryAddress":
orderRequest.addressId == 0 ? {} : {"Id": orderRequest.addressId},
"InBranch": orderRequest.inBranch,
"TableNumber": orderRequest.tableNumber.toString(),
"OrderItems": orderRequest.items,
"PromoCode": orderRequest.promoCodeId == 0
? {}
: {"Id": orderRequest.promoCodeId}
});
print("Url: " + url);
print("Token: " + accessToken);
print("Params: " + bodyParams);
final response = await retry(
() => http
.post(url,
headers: {
"content-type": "application/json",
"Accept": "application/json",
"Authorization": "Bearer " + accessToken
},
body: json.encode(bodyParams))
.timeout(Duration(seconds: 5)),
retryIf: (e) => e is SocketException || e is TimeoutException);
final responseData = json.decode(response.body);
print(responseData);
if (response.statusCode == 200) {
} else if (response.statusCode == 401) {
throw AuthException("401", responseData['Message']);
} else {
throw HttpException(responseData['Message']);
}
} catch (error) {
print(error);
throw error;
}
}
and in my screen class i create a method to upload my data to the server which i use it when i press a button which handle the post request :
Future<void> _addOrder() async {
OrderRequest request = OrderRequest();
request.addressId = _selectedAddress.id;
request.branchId = int.parse(_selectedBranchId);
request.inBranch = _selectedAddress.id == 0;
request.items = _cartItemsList;
request.promoCodeId = _promoCodeId;
request.tableNumber = _tableNumber;
try {
setState(() {
_isLoading = true;
});
await Provider.of<OrderProvider>(context).addOrder(request);
Provider.of<CartProvider>(context).emptyCart();
_showDialog("Order Sent", "Your order is sent to restaurant.");
} on HttpException catch (error) {
_showDialog("Error adding order", error.message);
} on SocketException catch (_) {
_showDialog("Error adding order",
"Please check your internet connection and try again");
} on TimeoutException catch (_) {
_showDialog("Error adding order",
"Please check your internet connection and try again");
} on AuthException catch (_) {
_refreshToken();
} catch (error) {
print(error);
_showDialog("Error adding address", "Something went wrong");
}
}
but when i press a Order button t to send a post request to a server i got this error:
I/flutter (12421): {Message: Error:Object reference not set to an instance of an object.}
I/flutter (12421): HttpException: Error:Object reference not set to an instance of an object.
this is the model class that i use
class OrderRequest{
int branchId;
int addressId;
bool inBranch;
int promoCodeId;
int tableNumber;
List<CartItem> items;
OrderRequest(
{
this.branchId,
this.addressId,
this.inBranch,
this.promoCodeId,
this.tableNumber,
this.items});
}

How do I return error from a Future in dart?

In my flutter app, I have a future that handles http requests and returns the decoded data. But I want to be able to send an error if the status code != 200 that can be gotten with the .catchError() handler.
Heres the future:
Future<List> getEvents(String customerID) async {
var response = await http.get(
Uri.encodeFull(...)
);
if (response.statusCode == 200){
return jsonDecode(response.body);
}else{
// I want to return error here
}
}
and when I call this function, I want to be able to get the error like:
getEvents(customerID)
.then(
...
).catchError(
(error) => print(error)
);
Throwing an error/exception:
You can use either return or throw to throw an error or an exception.
Using return:
Future<void> foo() async {
if (someCondition) {
return Future.error('FooError');
}
}
Using throw:
Future<void> bar() async {
if (someCondition) {
throw Exception('BarException');
}
}
Catching the error/exception:
You can use either catchError or try-catch block to catch the error or the exception.
Using catchError:
foo().catchError(print);
Using try-catch:
try {
await bar();
} catch (e) {
print(e);
}
You can use throw :
Future<List> getEvents(String customerID) async {
var response = await http.get(
Uri.encodeFull(...)
);
if (response.statusCode == 200){
return jsonDecode(response.body);
}else{
// I want to return error here
throw("some arbitrary error"); // error thrown
}
}
Another way to solve this is by using the dartz package.
An example of how to use it would look something similar like this
import 'package:dartz/dartz.dart';
abstract class Failure {}
class ServerFailure extends Failure {}
class ResultFailure extends Failure {
final int statusCode;
const ResultFailure({required this.statusCode});
}
FutureOr<Either<Failure, List>> getEvents(String customerID) async {
try {
final response = await http.get(
Uri.encodeFull(...)
);
if (response.statusCode == 200) {
return Right(jsonDecode(response.body));
} else {
return Left(ResultFailure(statusCode: response.statusCode));
}
}
catch (e) {
return Left(ServerFailure());
}
}
main() async {
final result = await getEvents('customerId');
result.fold(
(l) => print('Some failure occurred'),
(r) => print('Success')
);
}
You can return the error data like this if you want to read the error object:
response = await dio.post(endPoint, data: data).catchError((error) {
return error.response;
});
return response;
//POST
Future<String> post_firebase_async({String? path , required Product product}) async {
final Uri _url = path == null ? currentUrl: Uri.https(_baseUrl, '/$path');
print('Sending a POST request at $_url');
final response = await http.post(_url, body: jsonEncode(product.toJson()));
if(response.statusCode == 200){
final result = jsonDecode(response.body) as Map<String,dynamic>;
return result['name'];
}
else{
//throw HttpException(message: 'Failed with ${response.statusCode}');
return Future.error("This is the error", StackTrace.fromString("This is its trace"));
}
}
Here is how to call:
final result = await _firebase.post_firebase_async(product: dummyProduct).
catchError((err){
print('huhu $err');
});