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()));
}
Related
Getting an err in user registration through API in flutter.
Using postman I can successfully add user through deployed URL.
Error:
I/flutter (22622): 500 I/flutter (22622): POST
https://ecommerce-buer........../api/v1/user/register E/flutter
(22622): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled
Exception: NoSuchMethodError: The method '[]' was called on null.
E/flutter (22622): Receiver: null E/flutter (22622): Tried calling:
[]("success") E/flutter (22622): #0
Source Code:
doRegister(String username, String email, String password, String phoneno,
String city) async {
var res =
await userRegister(username, email, password, phoneno, city);
if (res['success']) {
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => LoginPage()));
} else {
}
}
Future userRegister(String username, String email, String password, String phoneno,
String city) async {
print(username);
print(email);
print(password);
print(phoneno);
print(city);
final response = await http.post(
Uri.parse(
'...url.../api/v1/user/register'),
headers: {
"Accept": "Application/json"
},
body: {
'name': username,
'email': email,
'password': password,
"phoneno": phoneno,
"city": city,
},
);
print(response.statusCode);
print(response.request);
if (response.statusCode == 200) {
var decodedData = jsonDecode(response.body);
return decodedData;
}
return null;
}
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']!);
I am trying to create a simple test but I keep getting this error.
type 'Null' is not a subtype of type 'Future'
test.dart
import 'package:flutter_test/flutter_test.dart';
import 'package:async/async.dart';
import 'package:http/http.dart' as http;
import 'package:mocktail/mocktail.dart';
class MockClient extends Mock implements http.Client {}
void main() {
group('signin', () {
final client = MockClient();
final api = AuthApi('https://baseUrl', client);
final credential = Credential(
email: 'test#test.com',
type: AuthType.email,
password: 'pass',
);
test('should return error when status code is not 200', () async {
registerFallbackValue(Uri.parse(''));
when(() => client.post(any(), body: {}))
.thenAnswer((_) async => http.Response('{}', 404));
final result = await api.signIn(credential);
expect(result, isA<ErrorResult>());
});
});
}
Error is at line
final result = await api.signIn(credential); expect(result,
isA());
If I remove those lines I don't see the error.
auth_api.dart
class AuthApi implements IAuthApi {
AuthApi(this.baseUrl, this._client);
final http.Client _client;
String baseUrl;
#override
Future<Result<String>> signIn(Credential credential) async {
final endpoint = Uri.parse(baseUrl + '/auth/signin');
return await _postCredential(endpoint, credential);
}
#override
Future<Result<String>> signUp(Credential credential) async {
final endpoint = Uri.parse(baseUrl + '/auth/signup');
return await _postCredential(endpoint, credential);
}
Future<Result<String>> _postCredential(
Uri endpoint,
Credential credential,
) async {
final response =
await _client.post(endpoint, body: Mapper.toJson(credential));
if (response.statusCode != 200) {
return Result.error('Server Error');
}
var json = jsonDecode(response.body);
return json['auth_token'] != null
? Result.value(json['auth_token'])
: Result.error(json['message']);
}
}
I checked other similar question answers also but none of them worked. I am using mocktail package & http for post.
The problem is in that line:
when(() => client.post(any(), body: {}))
.thenAnswer((_) async => http.Response('{}', 404));
It means that when there's a client.post() method invoked with any() URL and a specific empty body {}, then it should return a mocked response.
What you want is to return a mocked response when there's any URL and any body, so it should be like this:
when(() => client.post(any(), body: any(named: 'body')))
.thenAnswer((_) async => http.Response('{}', 404));
However, if you want to test if a specific error is thrown, that code should be modified:
test('should return error when status code is not 200', () async {
when(() => client.post(any(), body: any(named: 'body')))
.thenThrow(ErrorResult(Exception()));
expect(() async => await api.signIn(credential),
throwsA(isA<ErrorResult>()));
});
First, you specify that calling API should throw an error (when(...).thenThrow(...)) and then you check if an error was thrown (expect(..., throwsA(...)))
I am trying to persist the user authentication state of an already working auth system using flutter_bloc and Nodejs, by storing my successfully retrieved and generated JWTs. I have chosen flutter_secure_storage (FSS), for brevity as my key-value cache system.
Whenever I try to read or write data with FSS, I keep running into these kind of errors:
Unhandled Exception: NoSuchMethodError: The method 'write/read/delete' was called on null.
In the case of writing my JWTs to FSS, here's an example snippet:
#override
Future<UserModel> loginUser(Map<String, dynamic> body) async {
final userModel = await dataSource.loginUser(body);
var userId = userModel.id;
Future.delayed(Duration(seconds: 2), () async {
await storage.write(key: APIConstants.USER_ID_KEY, value: userId);
});
return userModel;
}
Have even tried delaying the write operation to see if the value will save, it only logs me in cos of proper credentials and then throws an error, not crashing though, that's great.
Here's the data source class snippet for login user:
abstract class UserRemoteDataSource {
Future<UserModel> loginUser(Map<String, dynamic> body);
Future<UserModel> registerUser(Map<String, dynamic> body);
// Future<User> sendOTP();
// Future<User> verifyOTP();
Future<UserModel> getCurrentUser(String userId);
Future<void> logOut();
}
class UserRemoteDataSourceImpl implements UserRemoteDataSource {
final APIClient client;
var storage = FlutterSecureStorage();
UserRepository repository;
UserRemoteDataSourceImpl({#required this.client});
#override
Future<UserModel> loginUser(Map<String, dynamic> body) async {
final response = await client.postAuthData('login', body);
final userResponseModel = UserResponseModel.fromJSON(response);
final accessToken = userResponseModel.accessToken;
final refreshToken = userResponseModel.refreshToken;
storage = FlutterSecureStorage();
await storage.write(key: APIConstants.ACCESS_TOKEN_KEY, value: accessToken)
.then((value) => print('AccessToken Written to FSS')); // this callback from future logs, so I know that the tokens have been saved
await storage.write(key: APIConstants.REFRESH_TOKEN_KEY, value: refreshToken)
.then((value) => print('RefreshToken Written to FSS'));
return userResponseModel.user;
}
#override
Future<UserModel> registerUser(Map<String, dynamic> body) async {
final response = await client.postAuthData('register', body);
final userResponseModel = UserResponseModel.fromJSON(response);
final accessToken = userResponseModel.accessToken;
final refreshToken = userResponseModel.refreshToken;
storage = FlutterSecureStorage();
await storage.write(key: APIConstants.ACCESS_TOKEN_KEY, value: accessToken)
.then((value) => print('AccessToken Written to FSS'));
await storage.write(key: APIConstants.REFRESH_TOKEN_KEY, value: refreshToken)
.then((value) => print('AccessToken Written to FSS'));
return userResponseModel.user;
}
#override
Future<UserModel> getCurrentUser(String id) {
return null; // cos of write and read operation for userid, had to just return null for now
}
#override
Future<void> logOut() async {
await client.postAuthData('logout', null);
}
}
Now, when I compile my code, cos of the Delayed Future in Repository Snippet (First One Above), I get this error (showing full logs):
I/flutter ( 5048): Login state is LoginStateInitial
I/flutter ( 5048): LoginState Listened is: LoginStateLoading
I/flutter ( 5048): LoginState Building is: LoginStateLoading
I/flutter ( 5048): {success: true, message: Logged in Successfully, user: {_id: 60435f3a0b5da10015bb87b3, username: abc123, email: abc123#gmail.com, password: $2b$10$wgdBFyvWUI4e0bB3KNRBl.WLLVwu2FVZQN9BtSSdxbSzfcwdQyH2K, phone: 89066060484, __v: 0}, accessToken: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE2MTgxMjU2NTEsImV4cCI6MTYyMDcxNzY1MSwiYXVkIjoiNjA0MzVmM2EwYjVkYTEwMDE1YmI4N2IzIiwiaXNzIjoicGlja3VycGFnZS5jb20ifQ.uH3D_v6mYwIOnBgRfoQQYzrN8asPt_Rhfei9wxmAM6A, refreshToken: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE2MTgxMjU2NTEsImV4cCI6MTY0OTY4MzI1MSwiYXVkIjoiNjA0MzVmM2EwYjVkYTEwMDE1YmI4N2IzIiwiaXNzIjoicGlja3VycGFnZS5jb20ifQ.dIgOHlsXdBXUtrLNqiF3mKhmKZU0HJe-IwMDyg23OO0}
D/FlutterSecureStoragePl( 5048): Initializing StorageCipher
I/fluttersecurestorage( 5048): Creating keys!
I/fluttersecurestorage( 5048): Initializing
I/fluttersecurestorage( 5048): Generating key pair
E/KeyStore( 5048): generateKeyInternal failed on request -68
D/FlutterSecureStoragePl( 5048): StorageCipher initialization complete
D/FlutterSecureStoragePl( 5048): StorageCipher already initialized
I/flutter ( 5048): LoginState Listened is: LoginStateSuccess
W/utter_bloc_aut( 5048): Accessing hidden method Lsun/misc/Unsafe;-
>compareAndSwapObject(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z (greylist, linking, allowed)
E/flutter ( 5048): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception:
// starts from here // NoSuchMethodError: The method 'write' was called on null.
E/flutter ( 5048): Receiver: null
E/flutter ( 5048): Tried calling: write(key: "userId", value: "60435f3a0b5da10015bb87b3") // in repository file
E/flutter ( 5048): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
E/flutter ( 5048): #1 UserRepositoryImpl.loginUser.<anonymous closure> (package:flutter_bloc_auth/data/repositories/user_repository_impl.dart:22:21)
E/flutter ( 5048): #2 UserRepositoryImpl.loginUser.<anonymous closure> (package:flutter_bloc_auth/data/repositories/user_repository_impl.dart:21:42)
E/flutter ( 5048): #3 new Future.delayed.<anonymous closure> (dart:async/future.dart:315:39)
Is this a prime example of using null safety and how? I had previously tried migrating the entire project to null safety but there were cyclic dependencies on the packages, so I continued without null safety.
Is this a case of using FutureBuilder to wait for the value of the strings (tokens and userid). Had tried calling .then but my response body (JSON String) is not a Future, obviously.
What's the cause of this error as we can see it later held the value of userId in E/flutter ( 5048): Tried calling: write(key: "userId", value: "60435f3a0b5da10015bb87b3") but initially it didn't, as per my understanding.
I've run into this error severally and still haven't found a way to deal with it. Any help will be appreciated.
--------EDIT (SIMILAR ISSUE)------
I've gotten the tokens and userid to save when login method is called. However, when I close the app and re-open it, it throws an error for reading the access token key (which was saved previously), like below log:
I/flutter (27570): AuthenticationStateInitial
I/flutter (27570): LoginState Building is: LoginStateInitial
I/flutter (27570): NoSuchMethodError: The method 'read' was called on null.
I/flutter (27570): Receiver: null
I/flutter (27570): Tried calling: read(key: "access_token")
I/flutter (27570): AuthenticationStateFailure
I want the AuthenticationBloc to read the state once it finds the token as Authenticated not Failure, each time a previously logged in or just signed up user opens the app. What's the best strategy for that?
Here's my AuthenticationBloc snippet. Login & Register Blocs Snippets Skipped Due to Brevity and Similarity of Functionality.
class AuthenticationBloc
extends Bloc<AuthenticationEvent, AuthenticationState> {
final UserRepository _repository;
AuthenticationBloc(UserRepository repository)
: assert(repository != null), _repository = repository,
super(AuthenticationStateInitial());
#override
Stream<AuthenticationState> mapEventToState(
AuthenticationEvent event) async* {
if (event is AppStarted) {
yield* _mapAppStartedToState(event);
}
if(event is UserSignedUp){
yield* _mapUserSignedUpToState(event);
}
if(event is UserLoggedIn){
yield* _mapUserLoggedInToState(event);
}
if(event is UserLoggedOut){
await _repository.deleteTokens(event.accessToken, event.refreshToken);
yield* _mapUserLoggedOutToState(event);
}
}
Stream<AuthenticationState> _mapAppStartedToState(AppStarted event) async*
{
yield AuthenticationStateLoading();
try{
// if(event?.accessToken == null || event.refreshToken == null) {
// yield AuthenticationStateUnAuthenticated();
// } else {
// print('accessToken is\t${event?.accessToken}');
// print('refreshToken is\t${event?.refreshToken}');
// try {
// final currentUser = await _repository.getCurrentUser();
// yield AuthenticationStateAuthenticated(user: currentUser, );
// } catch(error2) {
// print(error2);
// }
// }
final hasTokens = await _repository.checkHasTokens(event.accessToken, event.refreshToken); //simple read operation using the Keys used to write tokens values
print('hasTokens $hasTokens');
final currentUser = await _repository.getCurrentUser();
// if(hasTokens && currentUser != null){
if(hasTokens){
yield AuthenticationStateAuthenticated(user: currentUser, );
} else {
yield AuthenticationStateUnAuthenticated();
}
} catch(err){
print(err);
// yield AuthenticationStateFailure(errorMessage: err.message ?? 'Error Completing Your Request, Try Again!');
yield AuthenticationStateFailure(errorMessage: 'Error Completing Your Request, Try Again!');
}
}
Stream<AuthenticationState> _mapUserSignedUpToState(UserSignedUp event) async* {
yield AuthenticationStateAuthenticated(user: event.user);
}
Stream<AuthenticationState> _mapUserLoggedInToState(UserLoggedIn event) async* {
yield AuthenticationStateAuthenticated(user: event.user);
}
Stream<AuthenticationState> _mapUserLoggedOutToState(UserLoggedOut event) async* {
await _repository.logOut();
yield AuthenticationStateUnAuthenticated();
}
}
and UserRepositoryImpl Snippet, as Suggested:
class UserRepositoryImpl extends UserRepository {
final UserRemoteDataSource dataSource;
UserRepositoryImpl({#required this.dataSource});
var storage;
#override
Future<UserModel> loginUser(Map<String, dynamic> body) async {
final userModel = await dataSource.loginUser(body);
// var userId = userModel.id;
// Future.delayed(Duration(seconds: 2), () async {
// await storage.write(key: APIConstants.USER_ID_KEY, value: userId);
// });
return userModel;
}
#override
Future<UserModel> registerUser(Map<String, dynamic> body) async {
final userModel = await dataSource.registerUser(body);
// await storage.write(key: APIConstants.USER_ID_KEY, value: userModel.id);
return userModel;
}
#override
Future<UserModel> getCurrentUser() async {
// final userId = await storage.read(key: APIConstants.USER_ID_KEY);
// final user = await dataSource.getCurrentUser(userId);
// return user;
return null;
}
#override
Future<void> logOut() async {
storage = FlutterSecureStorage();
await storage.delete(key: APIConstants.ACCESS_TOKEN_KEY);
await storage.write(key: APIConstants.REFRESH_TOKEN_KEY);
await dataSource.logOut();
}
#override
Future<void> saveTokens(String accessToken, String refreshToken) async {
final storage = FlutterSecureStorage();
print('st() accesstokenval\t:$accessToken');
await storage.write(key: APIConstants.ACCESS_TOKEN_KEY, value: accessToken);
await storage.write(key: APIConstants.REFRESH_TOKEN_KEY, value: refreshToken);
}
#override
Future<void> deleteTokens(String accessToken, String refreshToken) async {
storage = FlutterSecureStorage();
await storage.delete(key: APIConstants.ACCESS_TOKEN_KEY);
await storage.write(key: APIConstants.REFRESH_TOKEN_KEY);
}
#override
Future<bool> checkHasTokens(String accessToken, String refreshToken) async{
storage = FlutterSecureStorage();
final hasAT = await storage.read(key: APIConstants.ACCESS_TOKEN_KEY);
final hasRT = await storage.read(key: APIConstants.REFRESH_TOKEN_KEY);
return hasRT == null || hasAT == null ? false : true;
}
}
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);
}