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

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

Related

How to get part from JSON using 'response.stream.bytesToString()' instead of "(response.body) ['data']"

Edit 1:
I am new to Flutter, and coding altogether, so please answer in simple terms.
I can get a JSON string from this API: [https://reqres.in/api/users?page=1][1]. using jsonDecode(response.body)
And I can also get specific part within this JSON using
jsonDecode(response.body)['data'] // 'data' is a List[]
But Postman, generates this completely different code to get data from api.
Postman uses response.stream.bytesToString());
Now I want to keep using Postman's auto generated code, but tweek it such that I get only the List, 'data', from the API.
My full code is:
class ApiService {
Future<List<UserModel>> getData() async {
try{
Response response = await get( Uri.parse('https://reqres.in/api/users?page=2'));
List result = await jsonDecode(response.body)['data'];
if (response.statusCode == 200) {
print(response);
print('');
print(response.body);
print('');
print(result);
print('');
return result.map((e) => UserModel.fromJson(e)).toList();
}
else {
print(response.reasonPhrase);
throw Exception(response.reasonPhrase);
}
} catch(e){
print('Error AA gaya \n\n\n $e') ;
throw e;
}
}
}
------------
Postman generated code is:
==========================
var request = http.Request('GET', Uri.parse('https://reqres.in/api/users?page=2'));
a
http.StreamedResponse response = await request.send();
if (response.statusCode == 200) {
print(await response.stream.bytesToString());
}
else {
print(response.reasonPhrase);
}
[1]: https://reqres.in/api/users?page=1
your code is correct but the way you parse is wrong
Future<List<UserModel>> getData() async {
try{
Response response = await get( Uri.parse('https://reqres.in/api/users?page=2'));
if (response.statusCode == 200) {
var jdata = jsonDecode(response.body);
print(response);
print('');
print(response.body);
print('');
print(jdata);
print('');
return jdata['data'].map((e) => UserModel.fromJson(e)).toList();
}
else {
print(response.reasonPhrase);
throw Exception(response.reasonPhrase);
}
} catch(e){
print('Error AA gaya \n\n\n $e') ;
throw e;
}
}

How can I run IF conditions after getting the data from the database and not before?

I have this funtion which gets data from a database.
Future reg() async {
try {
getData().then((value) async {
Dio dio = Dio();
Response response = await dio.get(
'http://${value["serverIP"]}:${value["port"]}/${value["passwordMain"]}/reg/${controllerEmail.text}/${controllerPassword.text}/${controllerUsername.text}');
return response;
});
} catch (e) {}
}
Now I request the data and check for some conditions but, the if conditions are ran first before getting the data from the database and the data arrives after the complete execution of code (Which I know because it can print the correct data after checking the IF conditions).
else {
var response = await reg();
if (response != null) {
if (response.data == "done") {
showErrorDialog(context, "Done",
"Your Account has been Created, please Log in");
} else if (response.data == "key") {
showErrorDialog(
context,
"Incorrect API Key/Main Server Password",
"The API Key (Main Server Password) is Incorrect. Kindly, Ensure the Key.");
} else if (response.data == "email") {
showErrorDialog(context, "Account Already Exists",
"An Account already exists with this Email");
} else if (response.data == "username") {
showErrorDialog(context, "Account Already Exists",
"An Account already exists with this Username");
}
}
}
How can I run these IF conditions after getting the data from the database?
You're missing a return in your reg() function. Add one before your getData() call like this:
Future reg() async {
try {
return getData().then((value) async {
Dio dio = Dio();
Response response = await dio.get(
'http://${value["serverIP"]}:${value["port"]}/${value["passwordMain"]}/reg/${controllerEmail.text}/${controllerPassword.text}/${controllerUsername.text}');
return response;
});
} catch (e) {}
}
Now the function should be properly awaited because it is now returning a promise instead of nothing.
Alternatively, you might prefer to rewrite it using more async/await for easier comprehension, like this:
Future reg() async {
try {
const value = await getData();
Dio dio = Dio();
Response response = await dio.get(
'http://${value["serverIP"]}:${value["port"]}/${value["passwordMain"]}/reg/${controllerEmail.text}/${controllerPassword.text}/${controllerUsername.text}');
return response;
} catch (e) {}
}

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

Trying to make a request with http in 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

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');
});