How to use http request sessions in dart - flutter

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

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:

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

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

Line after await http response in Flutter app does not execute

I want to fetch a result from Flask API after sending http.MultipartFile request to server.
like this:
Future<String> upload(List<int> filename, String url) async {
//filename : binary conversion of string
//String url : api address
print("Inside Upload future!");
var request = http.MultipartRequest('POST', Uri.parse(url));
request.files.add(
http.MultipartFile.fromBytes('file', filename, filename: 'files.txt'));
print("Sending Request!");
http.Response response = await http.Response.fromStream(await request.send());
print("request sent! now returning");
var rtr = response.body;
return rtr;
}
But the problem is it does not return, and output after execution is The print after await is not executed why??:
Inside Upload future!
Sending Request!
I am sending a String to Flask API like:
It works correctly, it is receiving a string and then replying with the same string with some modifications.
#app.route('/test_api', methods=['GET', 'POST'])
def test_api():
uploaded_file = request.files['file']
file_content = uploaded_file.read().splitlines()
uploaded_file.seek(0)
file_pretty = uploaded_file.read()
a = runkey(file_pretty)
//takes string agrument and returns manipulated string
uploaded_file.seek(0)
filename = secure_filename(uploaded_file.filename)
resp = make_response(a)
resp.headers['Content-Type'] = 'text/plain;charset=UTF-8'
n = filename
resp.headers['Content-Disposition'] = 'attachment;filename='+'n'
return resp ```
I Solved this, By Adding
resp.headers['Access-Control-Allow-Origin'] = '*'
//before returning response to client
to the FlaskAPI response.
actually, I thought there's an error in Dart somewhere. But it was hiding in Chrome debugging, Since I am using Flutter Web.
The error is of Cross-Origin not allowed due to access control.

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;

http.post is being fired twice

I am a bit new to Flutter, and I am building a screen that posts data to an API built in PHP mon my hosting server. The API is built by me which receives a JSON object and then saves the data.
The app is working fine, and API is receiving the data, but the http.post seems is firing twice ( calling the API twice)
Which makes my API saves the record twice. there is no possible way for me to check before adding the send record. as My API simply saves a new record so whenever it receives a call it simply saves it and returns back a value for the mobile App ( built in Flutter).
If I use a condition to check, this way the first call will return correct data to the mobile app, but the second one will return an error for the mobile app since the record already exists.
I have read about the Access-Control-Allow-Origin and how it might be the issue and put it my my .httaccess file
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "*"
</IfModule>
but no luck.
any idea.
Note I am using a shared hosting.
Code I use in Flutter:
class _PostADToServerState extends State<PostADToServer> {
Future<List<JSBResponse>> _postRequest() async {
// print('Call API function is called');
Map<String, dynamic> myAd = {
"isbn10": widget.title.isbn10,
"isbn13": widget.title.isbn13,
... [Some fields]
"titleCondition": widget.title.titleCondition,
"priceIs": widget.title.priceIs,
"school_name": widget.title.schoolName
};
String json = jsonEncode(myAd);
var url = 'https://www.example.com/xapis/save_new_ad.php';
var body = json;
var data = await http.post(url,
headers: {
"Content-Type": "application/json",
"accept": "application/json",
"Access-Control-Allow-Origin": "*",
},
body: body);
var jsonData = jsonDecode(data.body);
Code in my PHP API starts with the following:
$data = file_get_contents('php://input');
$theTitle = json_decode($data);
Then I use the content I find in the $theTitle object as the following:
$title = $theTitle->title;