How to get query params in a server request in flutter? - 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;

Related

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 display data which comes from async function?

I use api for get information which need to be display
Future <String> Get_Amount_Jackpot() async {
// SERVER LOGIN API URL
var url2 = 'https://www.easytrafic.fr/game_app/get_jackpot_lotto.php';
// Starting Web API Call.
var response2 = await http.get(url2,headers: {'content-type': 'application/json','accept': 'application/json','authorization': globals.token});
// Getting Server response into variable.
Map<String, dynamic> jsondata2 = json.decode(response2.body);
return jsondata2["value"];
}
I call it here :
void initState() {
ListLotto = Grille_display();
jackpot = Get_Amount_Jackpot();
super.initState();;
}
How i can display the value "jackpot" which is a simple number on mobile screen. Note i use futurebuilder for another api request, this is why it is complicated. Normally i use futurebuilder for display async data but there i need 2 différents api request so 2 futureBuilder ??? Is it possible and how do that ?
You can use then to get the returned value from the function.
Get_Amount_Jackpot().then((value){
//value is what is returned from the function
jackpot = value;
});
I'm not sure if you can use uppercase letter as the start of a function name, but i copied your function name for my answer. Hope this helps.

Dart HttpClient not reading full response

I have a weird issue using the dart HttpClient where it seems like it's not reading the full response before "finishing". This is the code I have:
HttpClient client = new HttpClient();
client.connectionTimeout = Duration(seconds: 60);
Completer<MealPlan> completer = new Completer();
RecipeSearchFilter filter = new RecipeSearchFilter();
filter.restrictions = intolerances.map((intolerance) => intolerance.name).toList();
MealPlan mealPlan;
client
.getUrl(Uri.parse(
"https://myUrl.com/api/meal-plans?filter=${jsonEncode(filter)}"))
.then((HttpClientRequest request) {
request.headers.set("Authorization", "Bearer $idToken");
return request.close();
}).then((HttpClientResponse response) {
response.transform(utf8.decoder).listen((contents) {
Map<String, dynamic> contentMap = jsonDecode(contents);
mealPlan = MealPlan.fromJson(contentMap);
}, onDone: () => completer.complete(mealPlan));
});
return completer.future;
This is the most intensive function that my app contains, so this particular API itself typically takes 6-8 seconds to fully complete since there's a lot going on behind the scenes. The response isn't big (~60KB). Making the exact same call using Postman I can see that it does indeed return everything as expected, but if I look at the response inside of the }).then((HttpClientResponse response) { block, it only contains a very small, partial bit of the response. I'm not sure what I'm doing wrong here, but I'm guessing that I've configured the HttpClient incorrectly.
The problem is that your response will be delivered by the stream in pieces. After passing those chunks through the utf8 decoder, you should then form them into a single string before trying to json decode it. Currently you try to json decode the first chunk without waiting for the rest.
It's much easier to use the package:http which is a wrapper around HttpClient, and does a lot of the grunt work for you. Also, it's more readable to use the async/await syntax rather than .then.
Using an async method you could write, for example:
void getPlan(Map filter, String idToken) async {
var response = await http.get(
Uri.parse('https://myUrl.com/api/meal-plans?filter=${jsonEncode(filter)}'),
headers: <String, String>{
'Authorization': 'Bearer $idToken',
},
);
return MealPlan.fromJson(json.decode(response.body));
}
If you really want to control the connection timeout, you need to pass in your own HttpClient, as follows:
var client =
http.IOClient(HttpClient()..connectionTimeout = Duration(seconds: 60));
var response = await client.get(
//etc

flutter get request with parameter

I am using Client() from http.dart. I am able to post with parameter but I have no idea how to do get with parameter. Post has body that takes the parameter but get doesn't.
I have tried
This is my client
Client httpClient = Client();
var response = await httpClient.get("controller/action/{parameter here}"
I hope this should solve your problem
fetchData() async {
Client httpClient = Client();
counter++;
var response =
await httpClient.get('https://jsonplaceholder.typicode.com/photos/$counter');
print(response.body);
}
i think you are saying that you want any kind of data to be sent to the server with GET request too,
you can not do it simply,
may be your parameter are the header of the Get ,
try passing your parameters in the header of GET

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