Ktor - sending form with binary data - kotlin-multiplatform

I am trying to send request to server:
client.submitFormWithBinaryData(
url = urlString,
formData = formData {
append("payload", file, Headers.build {
append("type", payload.type)
append("identifier", payload.identifier)
})
}){
headers {
append(HttpHeaders.ContentType, "multipart/form-data")
append("Mobile-Client-Type", header.mobile)
append("Mobile-Client-Version", header.version)
append("Authorization", header.authorisation)
}
In logs I can see that headers type and identifiers were not sent. How to fix that?

Related

Trying to upload media to the Meta Whatsapp API but running into errors

Context: I need to send media templates in which I need to send local files. Thus I need to upload the files to the WhatsApp API to get the Media Id, which I can then use to send the message templates.
The issue: I am running into errors while sending the post request to the server through DART. However the same call is working when sent through postman. I have tried sending the data both as a JSON and as form-data, but both are returning errors. I am attaching the code below, as well as the errors I am facing. Any help is really appreciated.
Getting the file path
upload() async{
if(await Permission.storage.isGranted){
FilePickerResult? choice = await FilePicker.platform.pickFiles(allowMultiple: false);
String? path = choice?.files.single.path;
if(path != null){
uploadJson(path);
// uploadFormData(path);
}
}else{
Permission.storage.request();
}
}
Uploading JSON
uploadJson(String path) async{
File imgfile = File(path);
Uint8List imgbytes = await imgfile.readAsBytes();
String bs4str = base64.encode(imgbytes);
print(bs4str);
var headers = {
'Authorization': variables.authorizationToken,
"Content-Type": 'application/json',
};
var body = jsonEncode({
'file': '$bs4str;type=image/jpeg',
'messaging_product':'whatsapp'
});
Response response = await post(Uri.parse('${variables.baseURL}${variables.phoneNumberId}/media'), headers: headers, body: body);
print(response.body);
}
Uploading as Form-data
uploadFormData(String path) async {
var headers = {
'Authorization': 'Bearer EAAGtvNhUHUIBANf5KvyxnZCUKcRn3jTJgPZBR2AbbVhZBZBO7GjoDCnS26FQT6Nr6qdRV993ZCJEbGwiqZCdQ7TZBJX8S6KXQdOTgmSf9ue7GCEN1IL3yqfAUEIN1bw0nyvptHeZBFCsdfwpxZAcS1ZCbCdmqArZC81orVbYRkzJy1h7ChOAygmrchfFtJAapykZAadruFqOWwcVvtudMezse94zENBNVZA0k7pAZD',
};
var request = MultipartRequest('POST', Uri.parse('https://graph.facebook.com/v14.0/106822672107550/media'));
request.fields.addAll({
'messaging_product': 'whatsapp'
});
request.files.add(await MultipartFile.fromPath('file', path));
request.headers.addAll(headers);
Response response = await Response.fromStream(await request.send());
print(response.body);
}
Error for JSON:
flutter: {"error":{"message":"An unknown error has occurred.","type":"OAuthException","code":1,"fbtrace_id":"AE72st2KT8wJFQ_wYvrcJY6"}}
Error for Form-Data:
flutter: {"error":{"message":"(#100) Param file must be a file with one of the following types: audio\/aac, audio\/mp4, audio\/mpeg, audio\/amr, audio\/ogg, audio\/opus, application\/vnd.ms-powerpoint, application\/msword, application\/vnd.openxmlformats-officedocument.wordprocessingml.document, application\/vnd.openxmlformats-officedocument.presentationml.presentation, application\/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application\/pdf, text\/plain, application\/vnd.ms-excel, image\/jpeg, image\/png, image\/webp, video\/mp4, video\/3gpp. Received file of type 'application\/octet-stream'.","type":"OAuthException","code":100,"fbtrace_id":"AfsxKl38CW7hUF_ixMzNha9"}}
The problem was with the Mime-type of the file. The Multi-Part file class needed the mime-type of the file to be declared while uploading the file, or the file was automatically being uploaded as an octlet-stream. The code to the working request is posted below.
var request = http.MultipartRequest('POST', Uri.parse('https://graph.facebook.com/v14.0/${variables.phoneNumberId}/media'));
request.headers.addAll({
'Authorization': variables.authorizationToken,
'Content-Type': 'multipart/form-data'
});
request.fields.addAll({
'messaging_product': 'whatsapp',
'type': 'application/pdf'
});
// The MIME type of the image or file
const mimeType = 'application/pdf';
// Open the image file
var file = File(path);
// Create a MultipartFile from the File object
final multipartFile = await http.MultipartFile.fromPath(
'file',
file.path,
contentType: MediaType.parse(mimeType),
);
// Create a request body containing the multipart file
request.files.add(multipartFile);
// Send the request
final response = await request.send();
// Check the response status code
if (response.statusCode == 200) {
String body = await response.stream.bytesToString();
var json = jsonDecode(body);
print(json['id']);
} else {
print(response.reasonPhrase);
}

IBM DataPower - How to handle HTML Response from openurl?

I tried looking for the solution in the forum but I was unable to find something similar to what I'm trying to achieve. I have a gateway script in an MPG which kinda looks like this:
session.INPUT.readAsJSON(function (error, json) {
if (error){
throw error;
} else {
var SAMLResponse = json['SAMLResponse'];
var RelayState = json['RelayState'];
var urlopen = require('urlopen');
var options = {
target: 'https://************.com/e32d32der2tj90g8h4',
method: 'POST',
headers: { 'HEADER_NAME' : 'VALUE'},
contentType: 'application/json',
timeout: 60,
sslClientProfile: 'ClientProfile',
data: {"SAMLResponse": SAMLResponse, "RelayState": RelayState}
};
urlopen.open(options, function(error, response) {
if (error) {
session.output.write("urlopen error: "+JSON.stringify(error));
} else {
var responseStatusCode = response.statusCode;
var responseReasonPhrase = response.reasonPhrase;
response.readAsBuffer(function(error, responseData){
if (error){
throw error;
} else {
session.output.write(responseData);
console.log(responseData);
}
});
}
});
}
});
I'm doing a POST request and the response I get from the urlopen function is an HTML page, how to I display the contents of that page in my browser? I need that to initiate a process flow. am I going in the wrong direction here? what's the best way to POST to a URI and display it's response in DataPower?
with regards to my experience with DataPower, I just started learning, So I might not be familiar with many of the concepts.
Thanks in Advance!
session.INPUT.readAsJSON() would indicate that you are receiving JSON data as the input (from the POST).
Since you are building this in a Multi-Protocol Gateway (MPGW) you need to set the Response type to non-xml if the response is HTML and if there is no backend call being made (other than the url-open()) you also must set the skip-backside=1 variable.
Is the scenario as:
JSON HTTP Request -> [MPGW] -> url-open() -> Backend server --|
HTTP Response <-----------------------------------------|
Or:
JSON HTTP Request -> [MPGW] -> url-open() --| (skip-backside)
HTTP Response <------------------------|
If there is no backend call I would recommend building this in a XML Firewall (XMLFW) service instead and set it to "loopback" and non-xml.
If there is a backend and that is where you are sending your HTML from the url-open() then only MPGW Response type needs to be set to non-xml.
If it is the second option the you can just set the payload and headers in GWS and just call the target (https://************.com/e32d32der2tj90g8h4) as teh MPGW backside connection, no need for the url-open().

How do you add CORS headers in Redstone interceptor?

I'm trying to add CORS headers to incoming requests but I've noticed that app.response.headers is an immutable map and app.request.response doesn't exist even though it appears in the documentation examples. So, to the OPTIONS request I'm replying using a new Shelf response, but I can't find a way to add any new headers to the response of the actual request. Any ideas?
#app.Interceptor(r"/api/.*", chainIdx: 1)
corsInterceptor() {
if (app.request.method == "OPTIONS") {
var response = new shelf.Response.ok("", headers: HEADERS);
app.chain.interrupt(statusCode: HttpStatus.OK, responseValue: response);
} else {
// app.request.response is not available
app.request.response.headers.add('Access-Control-Allow-Origin', '*');
app.chain.next();
}
}
I found the fix in the first piece of code inside the Interceptor documentation...:)
#app.Interceptor(r"/api/.*", chainIdx: 1)
corsInterceptor() {
if (app.request.method == "OPTIONS") {
var response = new shelf.Response.ok("", headers: HEADERS);
app.chain.interrupt(statusCode: HttpStatus.OK, responseValue: response);
} else {
app.chain.next(() => app.response.change(headers: HEADERS));
}
}
app.chain.next() can take a callback as argument, which is expected to return a Response object. In this case app.response.change() returns a response with the correct headers.

How can I upload a PDF using Dart's HttpClient?

I need to post a PDF file to a remote REST API, and I can't for the life of me figure it out. No matter what I do, the server responds that I have not yet associated an object with the file parameter. Let's say that I have a PDF called test.pdf. This is what I've been doing so far:
// Using an HttpClientRequest named req
req.headers.contentType = new ContentType('application', 'x-www-form-urlencoded');
StringBuffer sb = new StringBuffer();
String fileData = new File('Test.pdf').readAsStringSync();
sb.write('file=$fileData');
req.write(sb.toString());
return req.close();
Thus far, I've tried virtually every combination and encoding of the data that I write() to the request, but to no avail. I've tried sending it as codeUnits, I've tried encoding it using a UTF8.encode, I've tried encoding it using a Latin1Codec, everything. I'm stumped.
Any help would be greatly appreciated.
You can use MultipartRequest from the http package :
var uri = Uri.parse("http://pub.dartlang.org/packages/create");
var request = new http.MultipartRequest("POST", url);
request.fields['user'] = 'john#doe.com';
request.files.add(new http.MultipartFile.fromFile(
'package',
new File('build/package.tar.gz'),
contentType: new ContentType('application', 'x-tar'));
request.send().then((response) {
if (response.statusCode == 200) print("Uploaded!");
});
Try using the multipart/form-data header rather than x-www-form-urlencoded. This should be used for binary data, also can you show your full req request?
void uploadFile(File file) async {
// string to uri
var uri = Uri.parse("enter here upload URL");
// create multipart request
var request = new http.MultipartRequest("POST", uri);
// if you need more parameters to parse, add those like this. i added "user_id". here this "user_id" is a key of the API request
request.fields["user_id"] = "text";
// multipart that takes file.. here this "idDocumentOne_1" is a key of the API request
MultipartFile multipartFile = await http.MultipartFile.fromPath(
'idDocumentOne_1',
file.path
);
// add file to multipart
request.files.add(multipartFile);
// send request to upload file
await request.send().then((response) async {
// listen for response
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
}).catchError((e) {
print(e);
});
}
I used file picker to pick file.
Here is the codes for pick file.
Future getPdfAndUpload(int position) async {
File file = await FilePicker.getFile(
type: FileType.custom,
allowedExtensions: ['pdf','docx'],
);
if(file != null) {
setState(() {
file1 = file; //file1 is a global variable which i created
});
}
}
here file_picker flutter library.

Delete entry from database with WinJS and OData

I'm trying to delete an entry from the database by odata. I get the error message
{"error":{"code":"","message":{"lang":"en-US","value":"Bad Request - Error in query syntax."}}}
my code:
function deleteMonthEntry() {
var item = actMonthEntries.getItem(listIndex);
var queryString = "Stundens(" + item.data.datensatz_id + ")?$format=json";
var requestUrl = serviceUrl + queryString;
WinJS.xhr({
type: "delete",
url: requestUrl,
headers: {
"Content-type": "application/json"
}
}).done(
function complete(response) {
},
function (error) {
console.log(error);
}
);
}
My request URL looks like this:
requestUrl = "http://localhost:51893/TimeSheetWebservice.svc/Stundens(305233)?$format=json"
Thanks
Marlowe
At least I found the solution:
I've entered an filter request to my service like this:
TimeSheetWebservice.svc/Stundens?$filter=datensatz_id eq 305221
this returned the correct entry with this link:
TimeSheetWebservice.svc/Stundens(305221M)
So if I enter a M after the ID, everything works fin. But I have no idea where this M comes from.
Can anyone tell me the reason for this M? It does not belong to the ID. The ID is this
305221
Marlowe
Are you sure the server you're talking to supports the $format query option? Many don't. I would try removing that part of the request URI, and instead modify your headers value to specify an Accept header:
headers: {
"Content-Type": "application/json",
"Accept": "application/json"
}
For servers where $format is allowed, giving it a json value is equivalent to providing an Accept header with the application/json MIME type.
In general, for a DELETE operation, the Accept header or $format value only matters for error cases. With a successful DELETE, the response payload body will be empty, so there's no need for the server to know about your format preference.

Resources