Requests Library in flutter is not storing the cookies, when application exits - flutter

Earlier my app was using the flutter requests library 3.3.0, when i recently update the library to 4.4.1 . The cookie was not getting stored when the app exits. Is there a way to solve this without changing the package

I have got the solution to fix this issue.
Call a secure api, and automatically the cookies will get stored in the Request library. Fetch those cookies using the Requests.getStoredCookies(hostname) and convert the Cookie to string and store it in the shared preferences. And when the app exits and when the user comes back read the shared preferences and parse the string to cookiejar using the CookieJar.parseCookiesString(storedCooks!) and set the stored cookies using the Requests.setStoredCookies(hostname, parsedCookies) and now the problem is solved
SETTING THE COOKIES
String? url = env?.getBaseUrl();
String hostname = Requests.getHostname(url);
var r12 = await Requests.post(url,
headers: <String, String>{'authorization': authEncryptionKey!},
json: {"shouldGenerateCookie": true, "ipSession": false},
timeoutSeconds: 60, persistCookies: true);
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
var requestcookies = await Requests.getStoredCookies(hostname).then((value) =>
{
cookiesInString = value.values.first.toString()
});
sharedPreferences.setString('cookies', cookiesInString!);
The Cookies are set in the shared preferences, Reading the cookies
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
String? storedCooks = await sharedPreferences.getString("cookies");
String hostname = Requests.getHostname(url);
var parsedCookies = CookieJar.parseCookiesString(storedCooks!);
await Requests.setStoredCookies(hostname, parsedCookies);
var cookies = await Requests.getStoredCookies(hostname);
The cookies are been set to request library in the form of CookieJar

Related

Flutter api calls oauth_signature HMAC-SHA1 generation

I am trying to make an API call to my server everything works properly on postman but I can't seem to get it going on Flutter
String oauthConsumer ='oauth_consumer_key=[MyKey]';
String oauthNonce =
'oauth_nonce=${Random().nextInt(4294967296).toString()}';
String oauthCallback =
'oauth_callback=[MyCallback address]';
String oauthVersion = 'oauth_version=1.0';
String oauthTime =
'oauth_timestamp=${(DateTime.now().millisecondsSinceEpoch ~/ 1000).toString()}';
String oauthMethod = 'oauth_signature_method=HMAC-SHA1';
var oauthList = [
oauthCallback,
oauthConsumer,
oauthNonce,
oauthMethod,
oauthTime,
oauthVersion
];
oauthList.sort();
String oauthSig = //[I need a method to create this properly]
var request = http.Request('POST', Uri.parse([My URL]));
http.StreamedResponse response = await request.send();
if (response.statusCode == 200) {
print(await response.stream.bytesToString());
}
Like I mention postman does return the token and the token secret but trying on Flutter returns the Authentication Required error
Picture of the Postman request body
On the Authorization tab just filled in the Consumer Key and the Consumer Secret the headers where left untouched and default like this:

How to save API response in database?

I want to create an app with flutter that calls a Restful API and when the status code is 200 saves the response which is user information in a sqlite database.
I don't know how call API and save it in database so what can I do? Can somebody help me?
It's very simple
Your answer has two steps
Step 1: Call api
For this step, you can use the http package implemented for Flutter
Examples of http package codes can be seen from this link
https://pub.dev/packages/http/example
Step 2: Saving the response in the local database
For this step, you can also use the shared preference package, the sample code of which is available in the link below
https://pub.dev/packages/shared_preferences/example
I hope it was useful
To complete this task you need two packages from Pub.dev
Ready api get request : will return the data to store into the database
HTTP : This package contains a set of high-level functions and classes that make it easy to consume HTTP resources. It's multi-platform, and supports mobile, desktop, and the browser.
SQFLITE : SQLite plugin for Flutter. Supports iOS, Android and MacOS.
how to do it ?
you can do it in 4 steps :
Create the databse
Call the resource from http.get request
Format the data as you want to save it using json or string
Save the data to the sqfdatabase
var url =
Uri.https('www.yourApiLink.com', '/directory/expl/item', {'q': '{http}'});
// Await the http get response, then decode the json-formatted response.
var response = await http.get(url);
if (response.statusCode == 200) {
var jsonResponse =
convert.jsonDecode(response.body) as Map<String, dynamic>;
var itemCount = jsonResponse['totalItems'];
String response_str = jsonResponse.toString();
// Insert some records in a transaction
await database.transaction((txn) async {
int id1 = await txn.rawInsert(
'INSERT INTO Test(name, value, num) VALUES("some name", 1234, 456.789)');
print('inserted1: $id1');
int id2 = await txn.rawInsert(
'INSERT INTO Test(name, value, num) VALUES(?, ?)',
['response', $response_str]);
});
} else {
print('Request failed with status: ${response.statusCode}.');
}
You need first to do this for sqflite
// Get a location using getDatabasesPath
var databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'demo.db');
// open the database
Database database = await openDatabase(path, version: 1,
onCreate: (Database db, int version) async {
// When creating the db, create the table
await db.execute(
'CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT, value INTEGER, num REAL)');
});
Note : This is not a copy paste answer you have to adapt it to your
problem

How to use http request sessions in dart

Im struggling to figure out how to use sessions in flutter. In python I can for example do something like this for logging in:
s = requests.Session()
data = {'username':'user','password':'pass'}
s.post("https://example.com/login, data=data )
I can then make any new requests with the authenticated session:
s.get("https://example.com/myprofile")
In dart I tried this, which works fine and logs me in:
Map <String,String> data = {'username':'user','password':'pass'};
var url = Uri.parse('https://example.com/login');
var response = await http.post(url, body: data);
How do I use the same session once I'm logged in?
I tried the following which obviously didnt work:
var response = await http.get(url);

How to get query params in a server request in flutter?

In order to authenticate with Imgur on a mobile app, I decided to spawn an http server on port 8585 in order to complete the oauth flow. The request is read and a response is written, but I cannot access the queryparameters from the url.
I already tried using uri.queryparameters["access_token"], but null is returned.
the server is spawned as follows:
Future<Stream<String>> _server() async {
final StreamController<String> onCode = new StreamController();
HttpServer server =
await HttpServer.bind(InternetAddress.loopbackIPv4, 8585);
server.listen((HttpRequest request) async {
print(request.uri.hashCode);
final String accessToken = request.uri.queryParameters["access_token"];
request.response
..statusCode = 200
..headers.set("Content-Type", ContentType.html.mimeType)
..write("<html><h1>You can now close this window</h1></html>");
await request.response.close();
await server.close(force: true);
onCode.add(accessToken);
await onCode.close();
});
return onCode.stream;
}
the url the server gets is of the sort: http://localhost:8585/callback#access_token=your_token_here&expires_in=315360000&token_type=bearer&refresh_token=_your_refresh_token_here
Can anyone help me? I've been stuck on this for two whole days!
It returns null because query parameters start with ? at the beginning but in this link, there is a # before the query parameters and replacing it with a ? does solve the problem.
solution 1:
var uri =Uri.parse('http://localhost:8585/callback#access_token=your_token_here&expires_in=315360000&token_type=bearer&refresh_token=_your_refresh_token_here');
var newUri = Uri(query: uri.toString().substring(uri.toString().indexOf('#')+1));
print(newUri.queryParameters['access_token']) // your_token_here;
solution 2:
var uri =Uri.parse('http://localhost:8585/callback#access_token=your_token_here&expires_in=315360000&token_type=bearer&refresh_token=_your_refresh_token_here');
var newUri = Uri.parse(uri.toString().replaceFirst('#', '?'));
print(newUri.queryParameters['access_token']) // your_token_here;

Flutter http Maintain PHP session

I'm new to flutter. Basically I'm using code Igniter framework for my web application. I created REST API for my web app, after user login using API all the methods check for the session_id if it exists then it proceeds, and if it doesn't then it gives
{ ['status'] = false, ['message'] = 'unauthorized access' }
I'm creating app with flutter, when i use the http method of flutter it changes session on each request. I mean, it doesn't maintain the session. I think it destroys and creates new connection each time. Here is thr class method which i use for api calls get and post request.
class ApiCall {
static Map data;
static List keys;
static Future<Map> getData(url) async {
http.Response response = await http.get(url);
Map body = JSON.decode(response.body);
data = body;
return body;
}
static Future postData(url, data) async {
Map result;
http.Response response = await http.post(url, body: data).then((response) {
result = JSON.decode(response.body);
}).catchError((error) => print(error.toString()));
data = result;
keys = result.keys.toList();
return result;
}
I want to make API request and then store session_id,
And is it possible to maintain session on the server so i can manage authentication on the web app it self.?
HTTP is a stateless protocol, so servers need some way to identify clients on the second, third and subsequent requests they make to the server. In your case you might authenticate using the first request, so you want the server to remember you on subsequent requests, so that it knows you are already authenticated. A common way to do this is with cookies.
Igniter sends a cookie with the session id. You need to gather this from each response and send it back in the next request. (Servers sometimes change the session id (to reduce things like clickjacking that we don't need to consider yet), so you need to keep extracting the cookie from every response.)
The cookie arrives as an HTTP response header called set-cookie (there may be more than one, though hopefully not for simplicity). To send the cookie back you add a HTTP request header to your subsequent requests called cookie, copying across some of the information you extracted from the set-cookie header.
Hopefully, Igniter only sends one set-cookie header, but for debugging purposes you may find it useful to print them all by using response.headers.forEach((a, b) => print('$a: $b'));. You should find Set-Cookie: somename=abcdef; optional stuff. We need to extract the string up to, but excluding the ;, i.e. somename=abcdef
On the next, and subsequent requests, add a request header to your next request of {'Cookie': 'somename=abcdef'}, by changing your post command to:
http.post(url, body: data, headers:{'Cookie': cookie})
Incidentally, I think you have a mismatch of awaits and thens in your code above. Generally, you don't want statics in classes, if they should be top level functions instead. Instead you could create a cookie aware class like:
class Session {
Map<String, String> headers = {};
Future<Map> get(String url) async {
http.Response response = await http.get(url, headers: headers);
updateCookie(response);
return json.decode(response.body);
}
Future<Map> post(String url, dynamic data) async {
http.Response response = await http.post(url, body: data, headers: headers);
updateCookie(response);
return json.decode(response.body);
}
void updateCookie(http.Response response) {
String rawCookie = response.headers['set-cookie'];
if (rawCookie != null) {
int index = rawCookie.indexOf(';');
headers['cookie'] =
(index == -1) ? rawCookie : rawCookie.substring(0, index);
}
}
}