Common method for flutter api calls - flutter

Is there any example that I can refer to about Common class/method for flutter API calls(GET,POST,...) in flutter? I have handled all the API requests in a common method in react native, I'm not sure how to implement it in flutter.

you have to call getRequest using url parameter
Future<Response> getRequest(String url) async {
Response response;
try {
response = await _dio.get(url,
options: Options(headers: {
HttpHeaders.authorizationHeader:
'Bearer $accessToken'
}));
print('response $response');
} on DioError catch (e) {
print(e.message);
throw Exception(e.message);
}
return response;
}
here is the post method
Future<Response> posRequestImage(String url, data) async {
try {
response = await _dio.post(
url,
data: formData,
options: Options(headers: {
HttpHeaders.authorizationHeader:
'Bearer $accessToken'
}),
);
if (response.statusCode == 200) {
return response;
}
print('post response $response');
} on DioError catch (e) {
print(e.message);
throw Exception(e.response?.statusMessage);
}
return response;
}

You can create a class to handle it. For example, this is my class to handle all service for user model
import 'package:http/http.dart' as http;
class UserService {
var baseUrl = URL.devAddress;
Future<User> getUser() async {
final response = await http.get(
Uri.parse(baseUrl + "user/1")
);
if (response.statusCode == 200) {
final data = json.decode(response.body);
return data
} else {
throw Exception("Failed");
}
}
}

Future<void> getUser(String username) async {
Uri uri = Uri.parse('https://example.com');
try {
Map<String, dynamic> params = new HashMap();
params['username'] = username;
final response = await client.post(uri,
body: jsonEncode(params),
);
print("response ${response.body}");
} on FetchDataException {
throw FetchDataException("No Internet connection");
}
}

Related

How to implement try statement when sending http request?

I want to create a login method to post http request. I use the following code to post user data into the server and get a response:
import 'dart:convert';
import 'dart:html';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import '../Services/baseHttp.dart' as base;
class Services {
late var token = '';
Future<http.Response> login(String username, String password) async {
var url = base.BaseURL.loginUrl;
Map data = {"username": username, "password": password};
var body = json.encode(data);
var response = await http.post(Uri.parse(url),
headers: {
"Content-Type": "application/json",
"Accept": "application/json"
},
body: body);
print(response.statusCode);
token = response.body;
print(token);
return response;
}
}
I tried to use try catch inside the method:
Future<http.Response> login(String username, String password) async {
try {
var url = base.BaseURL.loginUrl;
Map data = {"username": username, "password": password};
var body = json.encode(data);
var response = await http.post(Uri.parse(url),
headers: {
"Content-Type": "application/json",
"Accept": "application/json"
},
body: body);
print(response.statusCode);
token = response.body;
print(token);
return response;
} catch (e) {
print(e);
}
}
I want to send statusCode instead of print(e) when any exception is thrown. How can I do that?
To check whether a response is valid, you can check the status code if it's equal to 200 like this:
if (response.statusCode == 200){
// Do something
} else {
// Throw exception
}
Taking a look the official documentation. You will see the following:
Future<Album> fetchAlbum() async {
final response = await http
.get(Uri.parse('https://jsonplaceholder.typicode.com/albums/1'));
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return Album.fromJson(jsonDecode(response.body));
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}

client.post login timeout not working in flutter

I need to use timeout if post request not working so, I write below code:
class APIService {
static var client = http.Client();
static Future<bool> login(LoginRequestModel model) async {
Map<String, String> requestHeaders = {
'Content-Type': 'application/json',
};
var url = Uri.http(Config.apiURL, Config.loginAPI);
try {
final response = await client
.post(
url,
headers: requestHeaders,
body: jsonEncode(model.toJson()),
)
.timeout(const Duration(seconds: 5));
print("response:");
print(response);
if (response.statusCode == 200) {
//SHARED
await SharedService.setLoginDetails(loginResponseJson(response.body));
return true;
} else {
return false;
}
} on TimeoutException catch (e) {
// handle timeout
return false;
}
}
But never end await client.post method waiting althouth I add timeout. How can I solve this ?
You can try this:
import 'package:http/http.dart' as http;
import 'package:http/io_client.dart' as http;
final body = { 'email': email, 'password': password };
final client = http.Client();
http.Response res;
try {
res = await client
.post(
url,
headers: requestHeaders,
body: jsonEncode(model.toJson()),
.catchError((e) {
// SocketException would show up here, potentially after the timeout.
})
.timeout(const Duration(seconds: 5));
} on TimeoutException catch (e) {
// Display an alert, no internet
} catch (err) {
print(err);
return null;
}

Flutter How to send Http (post) Request using WorkManager Plugin

Hello Guys any help will be apprecited please,
I am unable to send Http post or get request using workmanager plugin in flutter, any solutions to this would be highly appreciated, thanks
Here is my code
any help will be appreciated
thanks
Workmanager.executeTask((task, inputData) async {
switch (task) {
case fetchBackground:
print('checkStatusnow');
final sharedPref = await SharedPreferences.getInstance();
pendingStat = sharedPref.getBool('pendingStat');
print('pendingStat $pendingStat');
// await initialStat();
String url = 'https://getStat.com/chargeStat';
try {
var param = {
'authorization_code': authoStatCode,
'email': umail,
'amount': StatFare *100,
};
String body= json.encode(param);
var response = await http.Client().post(Uri.parse(url), headers: <String, String>{
'Authorization': StatKey,
'Content-Type': 'application/json',
'Accept': 'application/json'
},body: body,
);
if (response.statusCode == 200) {
print(response.body);
print("Successfull");
final data = jsonDecode(response.body);
print(data);
if (StatFounds == null) {
print("Status Not found");
}
else {
print ('checkForSta');
}
}
else {
print(response.reasonPhrase);
print("not available");
sharedPref.setBool("Stat", true);
}
} catch (e) {
}

flutter dio(4.0.0) handling token expiration (handling 401)

I have declared a class to make api requests using flutter Dio as follows.
class DioUtil {
static Dio _instance;
static Dio getInstance() {
if (_instance == null) {
_instance = createDio();
}
return _instance;
}
static Dio createDio() {
var dio = Dio();
dio.interceptors.add(InterceptorsWrapper(onRequest: (options, handler) {
// Do something before request is sent
return handler.next(options); //continue
}, onResponse: (response, handler) {
// Do something with response data
return handler.next(response); // continue
}, onError: (DioError e, handler) async {
if (e.response != null) {
if (e.response.statusCode == 401) {
var dio = DioUtil.getInstance();
dio.interceptors.requestLock.lock();
dio.interceptors.responseLock.lock();
RequestOptions requestOptions = e.requestOptions;
await refreshToken();
Repository repository = Repository();
var accessToken = await repository.readData("accessToken");
final opts = new Options(
method: requestOptions.method
);
dio.options.headers["Authorization"] = "Bearer " + accessToken;
dio.interceptors.requestLock.unlock();
dio.interceptors.responseLock.unlock();
dio.request(requestOptions.path,
options: opts,
data: requestOptions.data,
queryParameters: requestOptions.queryParameters);
}//TODO: handle else clause
}
}));
return dio;
}
static refreshToken() async {
Response response;
Repository repository = Repository();
var dio = Dio();
final Uri apiUrl = Uri.parse(BASE_PATH + "auth/reIssueAccessToken");
var refreshToken = await repository.readData("refreshToken");
dio.options.headers["Authorization"] = "Bearer " + refreshToken;
response = await dio.postUri(apiUrl);
if (response.statusCode == 200) {
LoginResponse loginResponse =
LoginResponse.fromJson(jsonDecode(response.toString()));
repository.addValue('accessToken', loginResponse.data.accessToken);
repository.addValue('refreshToken', loginResponse.data.refreshToken);
} else {
print(response.toString());
}
}
}
and I use flutter bloc pattern and my bloc is as follows.
class OurClassBloc extends Bloc<OurClassEvent, OurClassState> {
OurClassBloc(OurClassState initialState) : super(initialState);
Repository repository = Repository();
#override
Stream<OurClassState> mapEventToState(
OurClassEvent event,
) async* {
if (event is GetClasses) {
yield* _getClassCategories(event);
}
}
Stream<OurClassState> _getClassCategories(GetClasses event) async* {
Response response;
var dio = DioUtil.getInstance();
final String apiUrl = (BASE_PATH + "classCategories");
var accessToken = await repository.readData("accessToken");
Map<String, dynamic> map = {"active": event.active};
dio.options.headers["Authorization"] = "Bearer " + accessToken;
dio.options.headers["Accept"] = "*/*";
try {
response = await dio.get(apiUrl, queryParameters: map);
if (response.statusCode == 200) {
OurClassResponse loginResponse =
OurClassResponse.fromJson(jsonDecode(response.toString()));
yield OurClassSuccess(loginResponse);
}
if (response.statusCode >= 400) {
yield OurClassFailed();
}
} catch (e) {
yield OurClassFailed();
}
}
}
When I make the requests with valid access token, I get 200 status code in bloc class and api works fine.when the token is expired, the dio class correctly gets the new token, make the same api call with new token successfully and inside the below callback I get the correct response also.
onResponse: (response, handler) {
return handler.next(response);
}
but response doesn't comes to bloc class. Though it returned the response by calling return handler.next(response);,it is not coming to response variable inside _getClassCategories method.I expect the correct response should come to the response variable in bloc class for both scenarios:
makes the api call with valid token.
makes the api call with expired token.
but only scenario 1 is working in my code and hope someone here can help me to fix this.
EDIT- this works fine with dio previous version(3.0.10) - code
dio.request(requestOptions.path,
options: opts,
data: requestOptions.data,
queryParameters: requestOptions.queryParameters);
This line creates a new request with no relation to the original one. If the request succeeds, there is no code listening for a response. If you want the original caller to receive anything, you will need to forward the response to the original handler:
try {
final response = await dio.request(requestOptions.path,
options: opts,
data: requestOptions.data,
queryParameters: requestOptions.queryParameters);
handler.resolve(response);
} on DioError catch (error) {
handler.next(error); // or handler.reject(error);
}
Also, be sure to forward the error to the handler in non-401 cases as well. Dio 4.0.0 interceptors don't automatically forward anything.

How to set headers for POST with flutter and Dio

this is my code below, i'm stuck please help.
void getProducts() async {
String htoken = Utils.prefs.getString("token");
print(htoken);
try {
var dio = Dio(BaseOptions(headers: {"appusertoken": "$htoken"}));
//dio.options.headers["appusertoken"] = "$htoken";
Response response = await dio.post(
'APIURL',
);
print("data coming");
print(response.data);
} on DioError catch (e) {
print(e.response.data);
print(e.response.headers);
print(e.response.request);
}
}
it was throwing an error of data null.
I was able to fix the issues.
Add optional parameter options for dio.post method and define headers with Options class:
void getProducts() async {
String htoken = Utils.prefs.getString("token");
try {
Dio dio = Dio();
Response response = await dio.post("http://URL",
data: {},
options: Options(
headers: {"appusertoken": "$htoken"},
));
print("data coming");
print(response);
} on DioError catch (e) {
print(e.response.data);
print(e.response.headers);
print(e.response.request);
}
}
For example :
Dio _dio = new Dio();
_dio.options.contentType = Headers.formUrlEncodedContentType;
_dio.options.headers['Authorization'] = 'bearer $authToken';
or use :
final Map<String, dynamic> header = {'Authorization': 'bearer $authToken'};
enter code here
final responseData = await _dio.get(
Apis.account_profit,
options: RequestOptions(
method: 'GET', headers: header, baseUrl: Apis.apiBaseUrl),
);