How to execute an HTTP Get with Params, RequestHeaders and RequestContent - flutter

I'm a couple of weeks into my Flutter journey. I have looked at a few tutorials on using a web service and returning data, but am unsure of a couple of things and how to apply to my web services.
I have completed my web app (written in Elevate Web Builder) and also my server side modules acting as my web services. Inside my web app I call the web service using a server request and the following parameters:
Params : Key and value pairs - used to pass authorization info
eg:
Params.Values['userid'] := 'test'
Params.Values['password'] := 'test-Password'
RequestHeaders - used to specify the content type
eg:
RequestHeaders.Values['Content-Type'] := 'text/plain'
RequestContent : Key and value pairs - used to send values to specify what to retrieve or what to save into the database
eg:
RequestContent.Values['webService'] := 'Get_StaffList'
RequestContent.Values['CompanyId'] := '123'
RequestContent.Values['OnlyActive'] := 'Y'
The Params are specified as URL parameters, but I'm not sure where I specify the RequestHeaders and RequestContent?
I have tried sending RequestHeaders and RequestContent as:
http.post('https://...', headers: {'Content-Type': 'text/plain',
'webService': 'Get_StaffList',
'CompanyId': '123',
'OnlyActive': 'Y'
});
but this didn't work. Any ideas how it should be sent in Flutter?
Thanks heaps,
Paul

Here is an example
String server = "http://localhost:8008";
userSearch(String accessToken, String searchTerm) async {
String url = server + "/_matrix/client/r0/user_directory/search";
Map<String, String> headers = {"content-type": "application/json", "authorization": "Bearer $accessToken"};
String body = jsonEncode({"search_term": searchTerm});
Response response = await post(url, headers: headers, body: body);
UserSearchObj users = UserSearchObj.fromJson(jsonDecode(response.body));
return users;
}

I just thought I'd let you know I got it working. I took what you suggested and looked at what the web service was receiving from the web app. Then modified the code in Flutter to send the data in the same format. This now works:
final response = await http.post(
Uri.encodeFull('http://mobileuser.pvapps.one:82/modules/rmo_daMLogin'),
headers: {'Content-Type': 'text/plain'},
body: 'rmoService=User_Login\n'
'UserId=fred\n'
'Password=abc123');
Thanks again for the help,
Paul

Related

Flutter REST api call with Basic auth returns 401, despite correct credentials

I'm trying to call an api from flutter but i keep getting 401 Unauthorized. According to the api documentation it uses basic authentiocation and is UTF-8 encoded. The username and password is provided by the docs and if try the api in a web browser and enter those credentials it goes through and i recieve the data. This is the code i'm using in flutter:
Future<void> requestData() async {
String username = 'abc';
String password = '123';
String basicAuth = 'Basic ' + base64Encode(utf8.encode('$username:$password'));
Response r = await get(
Uri.parse('http://api.example.com'),
headers: {
HttpHeaders.authorizationHeader: basicAuth,
});
print(r.body);
print(r.statusCode);
}
I've also tried this variation which gave the same result:
headers: <String, String>{
'authorization': basicAuth
}
Seeing as the username and password are correct there must be something wrong with how i make the call, but i've tried to do it a bunch of different ways and nothing works. Any help would be greatly appreciated!
As per my experience, there is no need of token or basic auth while doing login. And login is post method not get.
Turns out the documentation i read was outdated/incorrect. The api uses "Digest authentication" which i looked up and was able to implement. This is the code if anyone is interested:
import 'package:http/http.dart';
import 'package:http_auth/http_auth.dart';
...
Response res = await DigestAuthClient("USERNAME", "PASSWORD")
.get(Uri.parse("API_URL")).timeout(const Duration(seconds: 20));

Works via Postman but not in Flutter: API call with GCS pre-signed URL

I'm trying to upload a video file to GCS using a pre-signed url. I've managed to create the url via Google but now I am facing a problem using it.
Upload works in Postman, got response 200.
postman body, postman params
Code copied from Postman results in 403 Forbidden (SignatureDoesNotMatch):
Future<http.StreamedResponse> uploadVideo(
{required String uploadURL, required String filePath}) async {
var headers = {'Content-Type': 'application/octet-stream'};
var request = http.MultipartRequest('PUT', Uri.parse(uploadURL));
request.files.add(await http.MultipartFile.fromPath('file', filePath));
request.headers.addAll(headers);
http.StreamedResponse response = await request.send();
if (response.statusCode == 200) {
print(await response.stream.bytesToString());
} else {
print(response.reasonPhrase);
}
return response;
}
This is the error I am getting from Google:
<?xml version='1.0' encoding='UTF-8'?><Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method.</Message><StringToSign>GOOG4-RSA-SHA256
20210803T082850Z
20210803/auto/storage/goog4_request
6d513846a3db49f949b0d2eea8f04b90f918b3b94588c3ed55ed3620b7d7e1f6</StringToSign><CanonicalRequest>PUT
/phonedo-interviews/app-test/007/2.mp4
X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=interviews%40interviews-317011.iam.gserviceaccount.com%2F20210803%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20210803T082850Z&X-Goog-Expires=900&X-Goog-SignedHeaders=content-type%3Bhost
content-type:multipart/form-data; boundary=dart-http-boundary-6w1yq6BQN3EkGBrhHZnwidOXZsBecsgSwTT3nBjB9vQCToHt0cg
host:storage.googleapis.com
content-type;host
UNSIGNED-PAYLOAD</CanonicalRequest></Error>
Note: I needed Content-Type to be application/octet-stream so I disabled that header in Postman's automatic headers and added Content-Type manually. When I didn't do that I also got 403.
The solution was to send the file in binary.
Here is the working code:
Future<http.Response> uploadVideo(
{required String uploadURL, required String filePath}) async {
var response = await http.put(
Uri.parse(uploadURL),
headers: {'content-type': 'application/octet-stream'},
body: File(filePath).readAsBytesSync(),
);
In your Postman headers, a Token is given to GCS (first line). Given that you need authorization, Postman probably has this Token saved somewhere application-wise.
In this flutter code, the headers you're giving do not include an Auth token and therefore you're receiving a 403 error.

http.post return 307 error code in flutter

I am using http client for flutter network call.
My request working on postman getting response properly,
But while trying with http.post it returns error code 307-Temporary Redirect,
Method Body:
static Future<http.Response> httpPost(
Map postParam, String serviceURL) async {
Map tempParam = {"id": "username", "pwd": "password"};
var param = json.encode(tempParam);
serviceURL = "http:xxxx/Login/Login";
// temp check
Map<String, String> headers = {
'Content-Type': 'application/json',
'cache-control': 'no-cache',
};
await http.post(serviceURL, headers: headers, body: param).then((response) {
return response;
});
}
Also, the same code returns a proper response to other requests and URLs.
First I trying with chopper client but had same issue.
I am unable to detect that issue from my end of from server-side.
Any help/hint will be helpful
Try to put a slash / at the end of the serviceUrl. So, serviceUrl is serviceURL = "http:xxxx/Login/Login/" instead of serviceURL = "http:xxxx/Login/Login".
This works for me.
You need to find a way to follow redirect.
Maybe postman is doing that.
Read this >>
https://api.flutter.dev/flutter/dart-io/HttpClientRequest/followRedirects.html
Can you try with using get instead of post? At least to try and see what happend
In the documentation said:
Automatic redirect will only happen for "GET" and "HEAD" requests
only for the status codes
HttpStatus.movedPermanently (301),
HttpStatus.found (302),
HttpStatus.movedTemporarily (302, alias for HttpStatus.found),
HttpStatus.seeOther (303),
HttpStatus.temporaryRedirect (307)
keeping https instead of http in the URL it is helping me.
#Abel's answer above is correct but I had to switch from using:
Uri url = Uri.https(defaultUri, path);
to
Uri url = Uri.parse('https://todo-fastapi-flutter.herokuapp.com/plan/');
to get that last / after plan.
The first way kept dropping it so I was getting 307 errors.
flutter.dev shows a full example:
Future<http.Response> createAlbum(String title) {
return http.post(
Uri.parse('https://jsonplaceholder.typicode.com/albums'),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{
'title': title,
}),
);
}
here: https://flutter.dev/docs/cookbook/networking/send-data#2-sending-data-to-server
For Dio Http Client, use Dio Option follow redirect as True
getDioOption(){
return BaseOptions(connectTimeout: 30, receiveTimeout: 30,
followRedirects: true);
}

How to send a token in a request in flutter?

I am making a flutter application, and i have written a server in django. When i send a token to my server for authentication then my server sends me an error of undefined token. Without token all requests works fine, but when i add a token then it gives me an error
{detail: Authentication credentials were not provided.}
But When i add token in modheader, my server works fine
Authorization: Token bff0e7675d6d80bd692f1be811da63e4182e4a5f
This is my flutter code
const url = 'MY_API_URL';
var authorization = 'Token bff0e7675d6d80bd692f1be811da63e4182e4a5f';
final response = await http.get(
url,
headers: {
'Content-Type': 'application/json',
'Authorization': authorization,
}
);
final responseData = json.decode(response.body);
print('responseData');
print(responseData);
try this:
Map<String, String> headers = {
HttpHeaders.contentTypeHeader: 'application/json',
HttpHeaders.acceptHeader: 'application/json',
HttpHeaders.authorizationHeader: 'Token bff0e7675d6d80bd692f1be811da63e4182e4a5f'
};
& use them in request
final response = await http.get(
url,
headers: headers,
);
As I don't know to work on your API so I can't tell you the exact answer.
Check that, Is your backend taking authorization by header or body or
I'll suggest you first make authorization by tools like postman then
if that succeeds then try to implement that in your app.

Node Js Restapi - Calling Post Method in Flutter Doesn't Work

I have local api and jwt by node js i want to send my username and password from flutter and send it to node js to give me this token and later i will save it in local storage but when i tell flutter post to the api doesn't post
my code :
You can use http method here like below Future example
Future postContact(access_token,name,email,phone,message) async {
String apiUrl = '$_apiUrl/user/contact-us';
http.Response response = await http.post(apiUrl,headers: {
"Accept": "application/json",
"Accesstoken": "Bearer $access_token"
}, body: {'name':'$name','email':'$email','phone':'$phone','message':'$message'});
print("Result: ${response.body}");
return json.decode(response.body);
}