I have login screen which will take a few fields and return a response.
login
login(String phn, String password) async {
final prefs = await SharedPreferences.getInstance();
await getLocation();
String uri = "$baseUrl/User_Login";
try {
http.Response response = await http.post(Uri.parse(uri), headers: {
'Accept': 'application/json'
}, body: {
"number": phn,
"password": password,
"long": long,
"lati": lati
});
prefs.setString('cookie', response.headers['set-cookie']!);
return json.decode(response.body);
} catch (e) {
return e;
}
}
and it will return
{status: success, Login_Key: f1278a9e15f48866beaeae2503f9b6d4, SESSION_ID: w00mRWDkIpGpz46WrilQ9mhRDyFEon8i0Zuqo89O}
and in Homepage I am getting data
getData() async {
final prefs = await SharedPreferences.getInstance();
String cookie = prefs.getString('cookie').toString();
String key = prefs.getString('authKey').toString(); // Login_key
String session = prefs.getString('sessionKey').toString(); // SESSION_KEY
String uri = "$baseUrlUser/user_bal";
var headers = {
'Accept': 'application/json',
'Authorization': 'Bearer $key',
'Cookie': cookie,
// 'Token': session,
};
print(headers); // shown
try {
http.Response response = await http.get(Uri.parse(uri), headers: headers);
return response.body;
} catch (e) {
return e;
}
}
and even after that getdata is returning response to the login page. It is working fine in Postman
this is what print(Headers) will do :
{Accept: application/json, Authorization: Bearer f1278a9e15f48866beaeae2503f9b6d4, Cookie: XSRF-TOKEN=eyJpdiI6ImZKRnJnZ090a3ZDUWw0UHhrbUpudXc9PSIsInZhbHVlIjoiNUFWVXNteFRqRE5FWjRRK3luN0xQNWpDa2FtRW5yN2dBRitSeDRaSkZzaGJsN29yZ0swcitSNFR2eWFVM1o3a044UTdFajg0a3NFSzdRbWFuc09qSXl5aFJiOXk4UzR0RTEraVd2THA2YytmRGVxVldla0JFdWhjWGdjVkpaeGwiLCJtYWMiOiI5YzFjZWM2YzBjMzk5ZWUyMjM5MjAzMWZmYTE4ZDY3MTBiMzMwMzU4MzY5MGVhODU5MzllNGIwZDQ1ODRjZTdmIiwidGFnIjoiIn0%3D; expires=Tue, 02-Aug-2022 12:14:43 GMT; Max-Age=7200; path=/; samesite=lax,laravel_session=eyJpdiI6ImhabnFOb0VHbzdCU0ExdzFHSis2UHc9PSIsInZhbHVlIjoiS0dXdTlZenQxVEdVTTd1NzRXdnE3UjBLSitKY1IrVE5FU2FvSXpxSEx2ZzBxVnJZRWhpbUx0UGZ0bklHVExiK3VDVVlSUFFHd3h6aUZQaWYybUg5RG45b0kzKzJmSEFFTERYajVXWUYycU1nWnVOa25zWnVGU0hhSzVPZXhzakYiLCJtYWMiOiJhN2VkZmUzZmIyMWQ4Zjg5MGMyY2MyMmY5ZTc3ZjhhZDhmMGVmYmJlMTkzMGZjZjBmMmFkMmFkY2NkOTNhN2QyIiwidGFnIjoiIn0%3D; path=/; httponly; samesite=lax}
In postman I getting this: which is what i want but in flutter I am getting this:
<!DOCTYPE html>
I/flutter (29556): <html lang="en">
I/flutter (29556): <head>
I/flutter (29556): <meta charset="utf-8">
I/flutter (29556): <meta name="viewport" content="width=device-width, initial-scale=1">
I/flutter (29556): <meta name="csrf-token" content="OJ0U3KwWLmfE9ym389vebecvFv5rk7u8AZErZEGX" />
I/flutter (29556): <title>Retailer Login | BharatAEPS</title>
I/flutter (29556):
I/flutter (29556): <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700&display=fallback">
I/flutter (29556):
I/flutter (29556): <link rel="stylesheet" href="../plugins/fontawesome-free/css/all.min.css">
I/flutter (29556):
I/flutter (29556): <link rel="stylesheet" href="../plugins/icheck-bootstrap/icheck-bootstrap.min.css">
I/flutter (29556):
I/flutter (29556): <link rel="stylesheet" href="../dist/css/adminlte.min.css">
I/flutter (29556): {Accept: application/json, Authorization: Bearer f1278a9e15f48866beaeae2503f9b6d4, Cookie: XSRF-TOKEN=eyJpdiI6IlIzcFF0WXdhM1NCLzYrem9YbXZuR3c9PSIsInZhbHVlIjoiVlJIRVBieXhXT0NramwwVVArcEdCd21KNHlPcUdweDRja0lTY1NGekl6aHFnOU1iTGhVWGZ0RHMrWGpSUVF4TlFvdi9DQmUydDJ0d2hCNDB6MllGTE5EMUpoWjFtNWJVdC9LS3p4a0J6QzNVT2Z3TE1zcisrTW1yWDdjdHpRTFYiLCJtYWMiOiI0NmY3YTA1OWIzMGE4MTE4NzZmMDViNjZjMDRjOTM1N2FmZWE1ZGVlZGM0MTg0Yjc0Yzc3ZTIwODNkYTBjMDUyIiwidGFnIjoiIn0%3D; expires=Tue, 02-Aug-2022 12:44:59 GMT; Max-Age=7200; path=/; samesite=lax,laravel_session=eyJpdiI6Ild4TmUxT2tRZXlkbWF1VkRhRmF4Ymc9PSIsInZhbHVlIjoiWHBYV1QzQTJtM09kVmpqVEg5WUJoT0N5c0w3cy9ZMUMyTmFQV1pKa3hkMGNlTnhTRTBOMjBkeHZlVlUxaEZ4QU5aNnd6R0VpV2lhNUhCOHBibExOWU9NeWZaMzBjTzVlMURyTG9QeUtldTc0QWRqd0Y3RTQrbG1obFZiaFBWU0giLCJtYWMiOiJmMmRmZDFiYzc1NjU4MDQ2NTI5ZTYxM2NlZDdlYzUxMzQ4NmY5MjQ2ZDc0M2Q5ODZjMTBjNzU1YWM5MzQ1ZDE0IiwidGFnIjoiIn0%3D; path=/; httponly; samesite=lax}
E/flutter (29556): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: This widget has been unmounted, so the State no longer has a context (and should be considered defunct).
I/flutter (29556): <link rel="stylesheet" href="https://aeps.bharataeps.com/css/loader/loader.css">
I/flutter (29556): <style type="text/css">
I/flutter (29556): .bgc{
I/flutter (29556): background: #FC466B; /* fallback for old browsers */
I/flutter (29556): background: -webkit-linear-gradient(to right, #3F5EFB, #FC466B); /* Chrome 10-25, Safari 5.1-6 */
I/flutter (29556): background: linear-gradient(to right, #3F5EFB, #FC466B); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
2
I/flutter (29556):
I/flutter (29556): }
I/flutter (29556): .hide{
To debug API response, you first need to know what is returned by your server.
Step 1
Print the error with the lined added below
try {
http.Response response = await http.get(Uri.parse(uri), headers: headers);
return response.body;
} catch (e) {
print(e); // add this and update your question
return e;
}
}
Step 2
Check the URL String uri = "$baseUrlUser/user_bal";, inside your Postman, the correct URL is User_Bal (Case sensitive maybe)
In your header you are getting a Cookie not a set-cookie so your code should be.
prefs.setString('cookie', response.headers['Cookie']!);
Related
I'm trying to implement the login functionality in my flutter app using Getx.
The problem is that it's always getting the api endpoint in a wrong way, an error I have never faced before and it's just strange. Here is the response when I execute the function:
I/flutter ( 6456): Response: <!DOCTYPE html>
I/flutter ( 6456): <html lang="en">
I/flutter ( 6456): <head>
I/flutter ( 6456): <meta charset="utf-8">
I/flutter ( 6456): <title>Error</title>
I/flutter ( 6456): </head>
I/flutter ( 6456): <body>
I/flutter ( 6456): <pre>Cannot POST /http:/localhost:4000/admin/user/login</pre>
I/flutter ( 6456): </body>
I/flutter ( 6456): </html>
Here is my api client class method:
const String BASE_URL = "http://localhost:4000";
Future<Response> postData(String endpoint, dynamic body) async {
final url = '$BASE_URL/$endpoint';
print(body.toString());
try {
Response response = await post(url, body, headers: _mainHeaders);
print('Response: ' + response.body.toString());
return response;
} catch (e) {
print('Error: ${e.toString()}');
return Response(statusCode: 1, statusText: e.toString());
}
}
And this is code from my auth repo:
Future<Response> login(String email, String password) async {
return await apiClient
.postData("/admin/user/login", {"email": email, "password": password});
}
Noting that the backend works perfectly and tested with postman as well, I don't know why it is reading the url as: "/http:/localhost:4000/admin/user/login" and not the way i'm passing it.
Edit:
dependencies file code:
Future<void> init() async {
final sharedPreferences = await SharedPreferences.getInstance();
Get.lazyPut(() => sharedPreferences);
//Api client
Get.lazyPut(() => ApiClient(appBaseUrl: "http://51.77.230.230:4001/server/"));
Get.lazyPut(
() => AuthRepo(apiClient: Get.find(), sharedPreferences: Get.find()));
//Repos
Get.lazyPut(() => CategoriesRepo(apiClient: Get.find()));
Get.lazyPut(() => ProductsRepo(apiClient: Get.find()));
Get.lazyPut(() => CartRepo(sharedPreferences: Get.find()));
Get.lazyPut(() => SubCategoriesRepo(apiClient: Get.find()));
//Controllers
Get.lazyPut(() => CategoriesController(categoriesRepo: Get.find()));
Get.lazyPut(() => ProductsController(productsRepo: Get.find()), fenix: true);
Get.lazyPut(() => CartController(cartRepo: Get.find()), fenix: true);
Get.lazyPut(() => SubCategoriesController(subCategoriesRepo: Get.find()),
fenix: true);
Get.lazyPut(() => AuthController(authRepo: Get.find()));
}
Hello there i am trying to download a pdf file with dio library but in the end i get this errror:
Hello there i am trying to download a pdf file with dio library but in the end i get this errror:
I/flutter (19900): 100%
I/flutter (19900): connection: keep-alive
I/flutter (19900): last-modified: Mon, 17 Oct 2022 10:17:34 GMT
I/flutter (19900): cache-control: no-cache, no-store, max-age=0, must-revalidate
I/flutter (19900): date: Fri, 21 Oct 2022 07:39:15 GMT
I/flutter (19900): vary: Origin
I/flutter (19900): vary: Access-Control-Request-Method
I/flutter (19900): vary: Access-Control-Request-Headers
I/flutter (19900): content-type: text/html;charset=UTF-8
I/flutter (19900): pragma: no-cache
I/flutter (19900): x-xss-protection: 1; mode=block
I/flutter (19900): content-language: en
I/flutter (19900): server: nginx/1.15.12
I/flutter (19900): accept-ranges: bytes
I/flutter (19900): content-length: 6425
I/flutter (19900): x-frame-options: DENY
I/flutter (19900): x-content-type-options: nosniff
I/flutter (19900): expires: 0
I/flutter (19900): FileSystemException: Cannot open file, path = '/data/user/0/com.iccs.electromobilityapp/cache' (OS Error: Is a directory, errno = 21)
Here is my code:
Future download2(Dio dio, String url, String savePath) async {
Directory tempDir = await getTemporaryDirectory();
tempPath = tempDir.path;
String? token = await this.widget.appController.storage.read(key: "token");
Map<String, String> headers = {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": "Bearer " + (token ?? ""),
};
try {
Response response = await dio.get(
url,
onReceiveProgress: showDownloadProgress,
//Received data with List<int>
options: Options(
headers: headers,
responseType: ResponseType.bytes,
followRedirects: false,
validateStatus: (status) {
return status! < 500;
}),
);
print(response.headers);
new File('$tempPath/file.xlsx').create(recursive: true);
File file = File(tempPath);
var raf = file.openSync(mode: FileMode.write);
// response.data is List<int> type
raf.writeFromSync(response.data);
await raf.close();
} catch (e) {
print(e);
}
}
I've written a simple function for you just pass a url and filename as an argument
downloadedFile({required String url, required String filename}) async {
var downloadsDirectoryPath = await getTemporaryDirectory()
final File file = File("/${downloadsDirectoryPath!.path}/$filename");
final response = await Dio().get(url, onReceiveProgress: (received, total) {
},
options: Options(
responseType: ResponseType.bytes,
followRedirects: false,
receiveTimeout: 0,
));
final raf = file.openSync(mode: FileMode.write);
raf.writeFromSync(response.data);
await raf.close();
return file;
}
Note: upvote and make the answer as correct if you find it useful.
I am getting this error while using mutate method of graphql_flutter package.
Tried with following versions of qraphql_flutter package:
5.0.1-beta.1
5.0.0
4.0.0-beta.5
Error:
I/flutter (13946): //// EXCEPTION: OperationException(linkException: ResponseFormatException(originalException: FormatException: Unexpected character (at character 1)
I/flutter (13946): <!DOCTYPE html>
I/flutter (13946): ^
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="refresh" content="0;url='https://xxx.xxx.dev/login'" />
<title>Redirecting to https://xxx.xxx.dev/login</title>
</head>
<body>
Redirecting to https://xxx.xxx.dev/login.
</body>
</html>
I/flutter (13946): ), graphqlErrors: [])
I tried running query using the same code.This code works perfectly fine with query, it only throws exception when using mutation.I created a graphql helper class which can help perform every graphql operation in project using this helper class.
GraphQL Helper Class:
import 'package:flutter/foundation.dart';
import 'package:graphql_demo/app_exception.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
class AppGraphQlClient {
late GraphQLClient _client;
AppGraphQlClient(String graphqlUrl) {
final httpLink = HttpLink(graphqlUrl);
_client = GraphQLClient(
link: AuthorizationLink(
}).concat(httpLink),
cache: GraphQLCache());
}
/// Perform mutation by passing query string
Stream<Map<String, dynamic>?> mutateString(String query, {required Map<String, dynamic> variables}) {
if (kDebugMode) {
print("MAP $variables");
}
return _client.mutate(MutationOptions(document: gql(query), variables: variables)).asStream().map((result) {
if (kDebugMode) {
print('//// RESULT: ${result.toString()}');
}
if (result.exception != null) {
if (kDebugMode) {
print('//// EXCEPTION: ${result.exception?.toString()}');
print('//// EXCEPTION: ${result.exception?.graphqlErrors}');
}
throw AppException(message: (result.exception !=null)?result.exception.toString():"Error");
}
return result.data;
});
}
}
class AuthorizationLink extends Link {
#override
Stream<Response> request(Request request, [NextLink? forward]) {
String token =
"authentication token goes here";
final header = Map<String, String>();
header['Authorization'] = '''Bearer $token''';
header['app_version'] = '3.2.3';
header['Accept-Language'] = 'en';
return forward!(request);
}
}
Can anyone provide a solution for this?
As you said, If you are getting error for mutation only, May be you are passing wrong token or wrong data.
Please check twice your code, must check token is passed whether it is valid or not.
i want to pass username and token from login screen to dashboard, i saved it using sharedpreference and call it to dashboard, i'm getting values too. but when i pass them to my api, using dio and print it's response.data it gives me Error wherease it's statuscode is 200. kindly help me with to fix this issue.
here is my code
var localhostUrl="http://10.0.2.2:8000/TimeIn";
_userDetails() async{
SharedPreferences myPrefs=await SharedPreferences.getInstance();
setState(() {
getname=myPrefs.getString('name');
getdesignation=myPrefs.getString('designation');
getTimeInStatus=myPrefs.getBool('timeInStatus');
getaccesstoken=myPrefs.getString('accesstoken');
});
}
calltimeInApi() async {
Dio dio=new Dio(
BaseOptions(
connectTimeout: 30000,
baseUrl: localhostUrl,
responseType: ResponseType.json,
contentType: ContentType.json.toString(),
));
var data={
'username':getname
};
dio.options.headers["authorization"] = "Bearer ${getaccesstoken}";
await dio.post(localhostUrl,data: data).then((onResponse) async {
print(onResponse.headers);
print(onResponse.statusCode);
print(onResponse.data);
;
});}
here is the output
I/flutter (14995): 1
I/flutter (14995): x-powered-by: Express
I/flutter (14995): connection: keep-alive
I/flutter (14995): keep-alive: timeout=5
I/flutter (14995): date: Wed, 09 Jun 2021 18:34:53 GMT
I/flutter (14995): content-length: 7
I/flutter (14995): etag: W/"7-Vuu5vA8hV5HSudFEr8bWQajjaE0"
I/flutter (14995): content-type: application/json; charset=utf-8
I/flutter (14995): 200 //statuscode
I/flutter (14995): Error //data
-----------Updated
i have tried all possible answers which i got from internet but no one resolves my problem
calltimeInApi() async {
Dio dio=new Dio(
BaseOptions(
connectTimeout: 30000,
baseUrl: localhostUrlTimeIn,
headers: {"Accept":"application/json"}
//contentType: ContentType.json.toString(),
));
var data={
"username":getname
};
dio.options.headers["authorization"] = "Bearer ${getaccesstoken}";
await dio.post(localhostUrlTimeIn,data: json.encode(data)).then((onResponse) async {
print(onResponse.headers);
if (onResponse.statusCode == 200) {
print(json.decode(onResponse.data));
} else {
print(onResponse.statusCode);
}
//print(onResponse.statusCode);
//print(json.decode(onResponse.data));
// print(response.statusCode);
// print(response.headers);
// print(response.statusMessage);
// print(response.data);
});}
here are logs of the above updated code
I/flutter (14995): 1
I/flutter (14995): x-powered-by: Express
I/flutter (14995): connection: keep-alive
I/flutter (14995): keep-alive: timeout=5
I/flutter (14995): date: Wed, 09 Jun 2021 19:20:41 GMT
I/flutter (14995): content-length: 7
I/flutter (14995): etag: W/"7-Vuu5vA8hV5HSudFEr8bWQajjaE0"
I/flutter (14995): content-type: application/json; charset=utf-8
E/flutter (14995): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: FormatException: Unexpected character (at character 1)
E/flutter (14995): Error
E/flutter (14995): ^
E/flutter (14995):
-----------------------------------UPDATED-----------------------------
i try to pass token in data, my api is working properly it response successfully according to my requirement but it's still giving me Error on response.data.
here is my update code
calltimeInApi() async {
Dio dio=new Dio();
var data={
'username': getname,
'token': getaccesstoken
};
await dio
.post(localhostUrlTimeIn,data: json.encode(data))
.then((onResponse) async {
print(onResponse.data);
print(onResponse.headers);
print(onResponse.statusCode);
}).catchError((onerror){
print(onerror.toString());
//showAlertDialog(context);
});
}
please help if anyone know how to fix it
//editing your dio
Dio createDio() {
//configure dio
Dio dio = Dio(BaseOptions(
connectTimeout: 50000,
receiveTimeout: 50000,
baseUrl: ApiPaths.BASE_URL,
));
;
//add interceptors
dio.interceptors.add(InterceptorsWrapper(
onRequest: (Options options, handler) async {
print('send request:path:${options.path},baseURL:${options.baseUrl}');
//==============fetch your token and parse it here as csrfToken============
if (csrfToken == null) {
print('no token,request token firstly...');
//lock the dio.
dio.lock();
//token null , try getting new token
handler.next(options);
}).catchError((error, stackTrace) {
handler.reject(error, true);
}) .whenComplete(() => dio.unlock()); // unlock the dio
} else {
//here add your token
options.headers["authorization"] = "Bearer $csrfToken";
handler.next(options);
}
}
));
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
(HttpClient client) {
client.badCertificateCallback =
(X509Certificate cert, String host, int port) {
final isValidHost = host == ApiPaths.BASE_URL;
return true;
};
return client;
};
return dio;
}
var dioHelper = createDio();
Edit your dio.post to match this . You nolonger need to create dio again. Anywhere you need to access dio use dioHelper
Response response= await dioHelper.post(localhostUrlTimeIn,data: json.encode(data));
print(response.statusCode)
print(response.data)
//you decode when parsing to an object model
I cannot take access token with this getData() function, it return "Bad Request - Invalid Hostname". How can ı fix this problem ? Am ı change Future<> method, async or http methods ?
Here is my main.dart :
Future<HttpClient> getData() async {
Map<String, String> connection = {
'grant_type': 'string',
'branchcode': 'string',
'password': 'string',
'username': 'string',
'dbname': 'string',
'dbuser': 'string',
'dbpassword': 'string',
'dbtype': 'string+'
};
var uri = Uri.http("192.168.1.44:7070","api/v2/token",connection);
http.Response r = await http.get(uri);
print(r.statusCode);
print(r.body);
}
ERROR !
I/flutter ( 9316): 400
I/flutter ( 9316): <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
I/flutter ( 9316): <HTML><HEAD><TITLE>Bad Request</TITLE>
I/flutter ( 9316): <META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>
I/flutter ( 9316): <BODY><h2>Bad Request - Invalid Hostname</h2>
I/flutter ( 9316): <hr><p>HTTP Error 400. The request hostname is invalid.</p>
I/flutter ( 9316): </BODY></HTML>
If you want to get token from rest api you have to post your connection with http.post() method.In this method you can easily declare the connection string in body field.I tried and it is working.
Here is my code block:
Future<Null> getData() async {
var url = "http://192.168.1.23:7070/api/v2/token";
http.post(url, body:{
"grant_type": "string",
"branchcode": "string",
"password": "string",
"username": "string",
"dbname": "string",
"dbuser": "string",
"dbpassword": "string",
"dbtype": "string"
}).then((response){
print("Response Status: ${response.statusCode}");
print("Response Body: ${response.body}");
});
}
I have tried to get the access token using unsplash api and it worked fine. I have used two plugins. first one, url_launcher, it allows you to open the url in a browser. you should put the registration url and once the user has successfully registered, user is redirected to your app. how? using the second plugin uni_links. once the user return back you start to extract the access token.
Launch the url that allow user to register
_launchURL() async {
var registerUrl= Constants.registerUrl;
if (await canLaunch(registerUrl)) {
await launch(registerUrl);
} else {
throw 'Could not launch $loginUrl';
}
}
when the user finish the process. your app should listen for this step
#override
initState() {
super.initState();
initUniLinks();
}
Future<Null> initUniLinks() async {
getUriLinksStream().listen((Uri uri) {
if (uri != null) {
setState(() {
String code = uri.queryParameters["code"];
print("code:" + code);
if (code != null) {
_getAccessToken(Constants.clientId, Constants.clientSecret,
Constants.redirectURI, code, "authorization_code");
}
});
}
}, onError: (err) {
print("error:" + err.toString());
});
}
_getAccessToken(String client_id, String client_secret, String redirect_uri,
String code, String grant_type) async {
var url = "https://unsplash.com/oauth/token";
var query_params = {
"client_id": client_id,
"client_secret": client_secret,
"redirect_uri": redirect_uri,
"code": code,
"grant_type": grant_type
};
var response = await http.post(url, body: query_params);
Map<String, dynamic> map = json.decode(response.body);
var accessToken = AccessToken.fromJson(map);
_saveAccessTokenToPrefs(accessToken);
}