HTTP rest api xml flutter authentication - rest

I'm trying to create a client app in flutter for a music server, the server uses this api http://www.subsonic.org/pages/api.jsp version 1.12.0
This is what I have so far:
import 'package:http/http.dart' as http;
main() async {
String username = 'demo';
String password = 'demo1';
String version = '1.12.0';
String client = 'democlient';
String basicAuth =
'Basic ' + base64Encode(utf8.encode('$username:$password$version$client'));
print(basicAuth);
Response r = await get('http://demo.org/rest/');
headers: {'authorization': basicAuth});
print(r.statusCode);
print(r.body);
Map <String, String> headers = {
'content-type': 'application/xml',
'accept': 'application/xml',
'authorization': basicAuth,
};
}
this is broken though.

Related

How to send raw data in flutter http

I wanted to send raw data in flutter http and the data doesn't look like JSON
Here's how I done that in Postman
and tried this in flutter using http,
Response res = await post(
Uri.parse(baseUrl + endPoint),
headers: {'Client-ID': clientId, 'Authorization': 'Bearer $accessToken'},
body: jsonEncode('fields *'),
);
and got this in console,
Error: XMLHttpRequest error.
Add it as this
var headers = {
'Accept': 'application/json',
'Content-Type': 'text/plain',
};
var request = http.Request('POST', Uri.parse('Your url'));
request.body = '''fields *''';
request.headers.addAll(headers);
http.StreamedResponse response = await request.send();
if (response.statusCode == 200) {
print(await response.stream.bytesToString());
}
else {
print(response.reasonPhrase);
}
Or you can easily see it being implemented in Postman's code request to the right just select the code icon and choose http-Dart

Flutter Resumable Upload to Google Drive Through HTTP

Based off the documentation on Google Drive API I'm trying to upload a file to the root folder of a Google Drive. I have authentication of the user through Google Sign In, and that hasn't been an issue. I keep getting a 411 Error returned from the server that says
"POST requests require a Content-length header. That’s all we know.".
I have a Content-length header but it seems to not be accepted. Here's the code I have,
Uri uri = Uri.parse('https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable');
http.MultipartRequest request = new http.MultipartRequest('POST', uri);
request.headers["Authorization"] = header['Authorization'];
request.headers['content-type'] = "application/json; charset=UTF-8";
request.headers['X-Upload-Content-Type'] ='video/mp4';
request.headers['X-Upload-Content-Length'] = lengthInBytes.toString();
request.headers['name'] = fileName;
request.headers['content-length'] = (request.contentLength).toString();
//request.files.add(await http.MultipartFile.fromPath('$fileName', file.path,));
print("request.toString: " + request.toString());
http.StreamedResponse response = await request.send();
print('ok: ' + response.statusCode.toString());
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
The only line that I know looks off to me is the fileName, as the documentation on the API site is slightly different and I'm not sure if I'm encoding it correctly. Here's the API example on the Google site,
POST https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable HTTP/1.1
Authorization: Bearer [YOUR_AUTH_TOKEN]
Content-Length: 38
Content-Type: application/json; charset=UTF-8
X-Upload-Content-Type: image/jpeg
X-Upload-Content-Length: 2000000
{
"name": "myObject"
}
I can do a multipart upload for a file about 5MB in size, but I need to be able to upload larger ones and resumable is the only option. I can post the multipart code that works if needed.
I solved the issue by using the http StreamedRequest class. The code posted below works with Google Drive V3 to upload a mp4 video.
Future handleUploadData(Map headers, String filename, String path) async {
final file = new File(path);
final fileLength = file.lengthSync().toString();
String sessionUri;
Uri uri = Uri.parse('https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable');
String body = json.encode({ 'name' : filename });
final initialStreamedRequest =
new http.StreamedRequest('POST', uri)
..headers.addAll({
'Authorization': headers['Authorization'],
'Content-Length' : utf8.encode(body).length.toString(),
'Content-Type' : 'application/json; charset=UTF-8',
'X-Upload-Content-Type' : 'video/mp4',
'X-Upload-Content-Length' : fileLength
});
initialStreamedRequest.sink.add(utf8.encode(body));
initialStreamedRequest.sink.close();
http.StreamedResponse response = await initialStreamedRequest.send();
print("response: " + response.statusCode.toString());
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
if (response.statusCode == 200) {
sessionUri = response.headers['location'];
print(sessionUri);
}
Uri sessionURI = Uri.parse(sessionUri);
final fileStreamedRequest =
new http.StreamedRequest('PUT', sessionURI)
..headers.addAll({
'Content-Length' : fileLength,
'Content-Type' : 'video/mp4',
});
fileStreamedRequest.sink.add(file.readAsBytesSync());
fileStreamedRequest.sink.close();
http.StreamedResponse fileResponse = await fileStreamedRequest.send();
print("file response: " + fileResponse.statusCode.toString());
fileResponse.stream.transform(utf8.decoder).listen((value) {
print(value);
});
}
The initial StreamRequest sends a request to GDrive with meta data about the file that will be uploaded, and receives a location URI that is used in the second file StreamRequest to upload the actual file data. Currently this is done in one upload action, but it could be split up into chunks.
I had roughly the same problem except I was trying to upload a text file and I wanted a single atomic request in order to be able to use the "If-Match" header with the file etag (When I'll write "update" code, I'm doing sync and I don't want to overwrite the file if it was changed by somewhere else during my sync).
I was really struggling with the http.post function and I was getting the "411 length required" error even though I was properly setting the "Content-Length" header.
The solution from Sean Coutinho using http.StreamedRequest gave me working code I could work from to get my request working, so thank you!
I'll post my code here in case it helps other people:
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:google_sign_in/google_sign_in.dart';
enum RemoteFileType {
FOLDER,
FILE,
}
class RemoteFile {
final RemoteFileType fileType;
final String fileId;
final String fileName;
RemoteFile(
this.fileType,
this.fileId,
this.fileName,
);
}
// The boundary string
const String MULTIPART_REQUESTS_BOUNDARY_STRING = 'foo_bar_baz';
Map<String, String> _authHeaders;
String _createMultiPartRequestBodyString(
final Map<String, dynamic> requestMetaData,
final String fileContentString,
) {
return '\r\n--$MULTIPART_REQUESTS_BOUNDARY_STRING\r\n' +
'Content-Type: application/json; charset=UTF-8\r\n\r\n' +
jsonEncode(requestMetaData) +
'\r\n--$MULTIPART_REQUESTS_BOUNDARY_STRING\r\nContent-Type: text/plain\r\n\r\n' +
fileContentString +
'\r\n--$MULTIPART_REQUESTS_BOUNDARY_STRING--';
}
Future<RemoteFile> createNewTextFile(
final RemoteFile parentFolder,
final String fileName,
final String fileTextContent,
) async {
final Map<String, dynamic> requestMetaData = {
'mimeType': 'application/json',
'title': fileName,
'parents': [
{'id': parentFolder.fileId}
],
};
final String multiPartRequestBodyString = _createMultiPartRequestBodyString(requestMetaData, fileTextContent);
final http.StreamedRequest fileStreamedRequest = http.StreamedRequest(
'POST',
Uri.parse('https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart'),
);
fileStreamedRequest.headers.addAll({
'Authorization': _authHeaders['Authorization'],
'Accept': 'application/json',
'Content-Type': 'multipart/related; boundary=$MULTIPART_REQUESTS_BOUNDARY_STRING',
'Content-Length': multiPartRequestBodyString.length.toString(),
//'If-Match': 'my_etag_here_when_updating_existing_file_with_put',
});
fileStreamedRequest.sink.add(utf8.encode(multiPartRequestBodyString));
fileStreamedRequest.sink.close();
final http.StreamedResponse httpPostResponse = await fileStreamedRequest.send();
// Do what you want with the response too
//...
}

Invalid Header Name In Flutter HTTP Request

I have a login page where i am trying to send a login request to my backend. But I get an Unhandled Exception: Invalid header field name. Here is my submit function
submit() async {
var res = await LoginAPI().loginData(
{'email': _emailController.value, 'password': _passwordController.value});
var body = json.decode(res.body);
print(body);
}
Then in my LoginAPI class here is my loginData function that makes the call to the backend
import 'dart:convert';
import 'package:http/http.dart' as http;
class LoginAPI {
final String _url = "http://10.0.2.2:8000/api/";
Map<String, String> headers = {"Content-type": "application/json"};
loginData(data) async {
var fullUrl = _url + "v1/users/login";
return await http.post(
fullUrl,
body: jsonEncode(data),
headers: headers
);
}
}
Here is my request through postman
Here is my response through postman
When I make the same request with Postman i get the response I am supposed to get. What Am i doing wrong?
try this
Map<String, String> headers = {"Content-type": "application/json", "Accept": "application/json",};
It looks from your postman request that you are just sending form data (not a json encoded body). package:http will form encode the body for you (and add the content type header) if you do the following:
return await http.post(
fullUrl,
body: data,
);
So i was able to solve the issue. The issue was with my CORS middleware on my server. I just made some changes and it worked fine. So if anyone has this issue just know it has nothing to do with flutter but most probably CORS

How to send parameters in headers using http package in flutter

I want to sent my auth-key in headers using http package but unfortunately its not working kindly help me .
var url = "https://paysafemoney.com/psmApi/Psm/userDashboard";
var response = await http.post(
url,
headers: {
"auth-key": LoginConfirmActivity.authKey,
},
body: sendLoginData,
);
print("Response = ${response.body}");
You can do like this
var fullUrl = '$stripeBaseUrl$customerId/sources?source=$cardToken';
var header = {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': stripeKey,
};
final response = await client.post(fullUrl, headers: header);

How to connect api in laravel of flutter apps?

How can I connect my flutter apps with laravel api? Below is what I post in postman.
http://10.0.2.2/voyce/api/register
I try to run the API in postman and it does not give any response.
here is my api.dart in flutter.
api.dart
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
class CallApi{
final String _url = 'http://10.0.2.2/voyce/api/';
postData(data, apiUrl) async {
var fullUrl = _url + apiUrl + await _getToken();
return await http.post(
fullUrl,
body: jsonEncode(data),
headers: _setHeaders()
);
}
getData(apiUrl) async {
var fullUrl = _url + apiUrl + await _getToken();
return await http.get(
fullUrl,
headers: _setHeaders()
);
}
_setHeaders() => {
'Content-type' : 'application/json',
'Accept' : 'application/json',
};
_getToken() async {
SharedPreferences localStorage = await
SharedPreferences.getInstance();
var token = localStorage.getString('token');
return '?token=$token';
}
}
All I want it to make the api able to connect? I think maybe there is something wrong with my laravel API but I dont have any idea where to fix it.
If you've encounter the error SocketException: OS Error: Connection refused, this is most likely a network connection error. When trying to post the url in the browser and you get the proper response, then the problem could be in the postman. But you can refer here for more details on how to integrate Laravel in Flutter.