dropbox-api get_thumbnail_v2 & get_thumbnail returns question marks(?) inside rhombs () - salesforce

I am trying to use DropBox API to get a thumbnail from DropBox and show them on Lightning Web Component in Salesforce, but can not do it because in a response Apex receiving body with black rhombs and question marks inside.
I use standard HTTP method to call
HttpRequest req = new HttpRequest();
req.setHeader('Authorization', 'Bearer sl.validToken');
req.setHeader('Dropbox-API-Arg', '{"resource": {".tag": "path","path": "/folderName/pictureName.jpg"},"format": "jpeg","size": "w64h64","mode": "strict"}');
req.setHeader('Content-Type', 'text/plain; charset=utf-8');
req.setEndpoint('https://content.dropboxapi.com/2/files/get_thumbnail_v2');
req.setMethod('POST');
Http httpreq = new Http();
HttpResponse res = httpreq.send(req);
this is what I receive in body of response in Apex. The same response I have in Postman.
https://i.stack.imgur.com/90yjI.png
This is what I have in DropBox explorer with same values and headers (JSON)
https://i.stack.imgur.com/ytDxv.png
File scope is Read to everyone. SF Remote Site Settings & CSP Trusted Sites are set.
Short update:
I`ve been able to get JSON From header. I did use that piece of code:
List<String> headers = new List<String>(res.getHeaderKeys());
for(String key : headers){
System.debug('key ->>> '+key+' = '+res.getHeader(key));
}
String jsonString = res.getHeader('Dropbox-Api-Result');
System.debug('->>>ddd '+jsonString);
But still do not understand how to use it as a thumbnail in LWC.
Thank you in advance for your help.

The /2/files/get_thumbnail_v2 Dropbox API endpoint is a "content-download" style endpoint, meaning the "response body contains file content, so the result will appear as JSON in the Dropbox-API-Result response header". So, the illegible value you're receiving is the actual bytes of the thumbnail data itself. You're currently attempting to display it as text, but you'll instead need to save and display it as an image to see the thumbnail. Refer to your platform's documentation for information on how to display an image.
For reference, the Dropbox API v2 Explorer is built with knowledge of the different endpoint formats, so in this case it displays the metadata from the Dropbox-API-Result response header, and just offers the file data, in this case the thumbnail data, as a download via a "Download" button.

Related

Is there any way to get content of the ZenDesk Attachments instead of redirect URL?

I need to get ZenDesk ticket attachment content like encoded format. ZenDesk API provided only the content url. By using that content url I can only able to get the redirect page of that file. But I need to automate a process that file as Base64 encoded format. Thanks in advance.
Note : I tried to migrate ZenDesk to Salesforce via Dell Boomi.
I found a resolution for my problem and I guess it's the same as yours.
In salesforce apex code I got the url response from zendesk and I used subtring method to get URL of attachment.
After that I used Pagereferece to open the URL, see below:
String exampleMyResponse= '<html><body>You are being <a href="https://xxx.zdusercontent.com/attachment/000001/sdlfkashdf98709udfah?token=eyJhbGciOiJkaX46SgYrFzTEpYqUIzpQeNnl5BMBNoRnUOsgQj389Ei7nNcGOcfGYaavlqLL2qaIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0..U8oX8QnYBM1lZMb6rhQGRA.NC3Z9kHC9ZE6HhygIHHan6xWYvoPqziVx76CZ6vcNYHBuAjV-LmBclVJYumKWKXA_PDhXX27z977XKYrLJZSc85a6lJTEqd-V2mP7U6O6r0_6E9hO8CWaA1dyxYYWw8kUsgMFUaPr0wCupxm3NbDzT03ZwO6EBJj79x4UZdauiXfEUrSwdl1pPahlQE2VfFo8DprgX9GQHzRFm5lwMrhA3crogo8Ox';
**//You need to authorize your domain "https://xxx.zdusercontent.com"** in remote site
Pagereference pg = new Pagereference(exampleMyResponse.substringAfter('href="'));
**Blob b = pg.getContentAsPDF();**//Here you can use getContent() too for another type of file
//Example to save PDF
Attachment att = new Attachment(Name = 'stvm_4', Body = b, ContentType = 'application/pdf', ParentId='Sobject_Id');
insert att;

POST multipart/form-data with NodeRed HTTP request

I'm trying to generate a HTTP Webrequest in NodeRed that will upload a file to a website via a normal upload form. I guess i knwo how to upload a file, but i do not know how to pass the other input fieds i have to fill also.
I only found how to set http headers:
msg.headers["content-type"] = "multipart/form-data";
This is what i have so far:
I have also tried in "the missing part" to write the FormData and send the Request manually. (https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects)
But also no luck with that. Only received an Error that FormData is unknown...
In the function node, before sending msg, set request header like this
msg.headers = {
"content-type":"application/x-www-form-urlencoded"
}

How can I convert a file received as blob in HttpResponse call to an audio file in Salesforce Apex coding?

I am actually trying to implement text-to-speech conversion in Salesforce by hitting a third-party api. When i send the request through Postman, i get back the proper response in .wav format. However, I'm not being able to handle this reponse programatically in salesforce end, as I am not able to store the response in any audio object.
Any assistance would be greatly appreciated.
Thanks in advance.
Abhishek.
Not 100% sure of what your trying to do but it would look something like this assuming you built your object correctly
ResponseObject result = new ResponseObject();
result = (InnerClasses.ResponseObject)JSON.deserialize(json, InnerClasses.ResponseObject.class);
This is supported by IBM's Watson Salesforce SDK, available here
The functional tests for Watson's text-to-speech services can be found here refer to the method
testSynthesize(String username, String password, String customizationId)
The audio file returned as part of the response could be saved as an attachment in Salesforce by simply creating it from the IBMWatsonFile like on this example,
IBMWatsonFile resp = textToSpeech.synthesize(options);
Attachment attachment = new Attachment();
attachment.Body = resp.body();
attachment.Name = resp.name();
attachment.ParentId = '<your salesforce parent id>';
insert attachment;
This code uses basically the method getBodyAsBlob() available from the HttpResponse class
before using this approach, please consider the governor limits enforced by Salesforce on any APEX callout, refer to the Maximum size of callout request or response documented here

Only one auth mechanism allowed; only the X-Amz-Algorithm query parameter..?

I am trying to send a PUT request to an amazonS3 presigned URL. My request seems to be called twice even if I only have one PUT request. The first request returns 200 OK, the second one returns 400 Bad Request.
Here is my code:
var req = {
method: 'PUT',
url: presignedUrl,
headers: {
'Content-Type': 'text/csv'
},
data: <some file in base64 format>
};
$http(req).success(function(result) {
console.log('SUCCESS!');
}).error(function(error) {
console.log('FAILED!', error);
});
The 400 Bad Request error in more detail:
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>InvalidArgument</Code>
<Message>Only one auth mechanism allowed; only the X-Amz-Algorithm query parameter, Signature query string parameter or the Authorization header should be specified</Message>
<ArgumentName>Authorization</ArgumentName>
<ArgumentValue>Bearer someToken</ArgumentValue>
<RequestId>someRequestId</RequestId>
<HostId>someHostId</HostId>
</Error>
What I don't understand is, why is it returning 400? and What's the workaround?
Your client is probably sending an initial request that uses an Authorization header, which is being responded with a 302. The response includes a Location header which has a Signature parameter. The problem is that the headers from the initial request are being copied into the subsequent redirect request, such that it contains both Authorization and Signature. If you remove the Authorization from the subsequent request you should be good.
This happened to me, but in a Java / HttpClient environment. I can provide details of the solution in Java, but unfortunately not for AngularJS.
For the Googlers, if you're sending a signed (signature v4) S3 request via Cloudfront and "Restrict Bucket Access" is set to "Yes" in your Cloudfront Origin settings, Cloudfront will add the Authorization header to your request and you'll get this error. Since you've already signed your request, though, you should be able to turn this setting off and not sacrifice any security.
I know this may be too late to answer, but like #mlohbihler said, the cause of this error for me was the Authorization header being sent by the http interceptor I had setup in Angular.
Essentially, I had not properly filtered out the AWS S3 domain so as to avoid it automatically getting the JWT authorization header.
Also, the 400 "invalid argument" may surface as a result of wrong config/credentials for your S3::Presigner that is presigning the url to begin with. Once you get past the 400, you may encounter a 501 "not implemented" response like I did. Was able to solve it by specifying a Content-Length header (specified here as a required header). Hopefully that helps #arjuncc, it solved my postman issue when testing s3 image uploads with a presigned url.
The message says that ONLY ONE authentication allowed. It could be that You are sending one in URL as auth parameters, another - in headers as Authorization header.
import 'package:dio/adapter.dart';
import 'package:dio/dio.dart';
import 'package:scavenger_inc_flutter/utils/AuthUtils.dart';
import 'package:scavenger_inc_flutter/utils/URLS.dart';
class ApiClient {
static Dio dio;
static Dio getClient() {
if (dio == null) {
dio = new Dio();
dio.httpClientAdapter = new CustomHttpAdapter();
}
return dio;
}
}
class CustomHttpAdapter extends HttpClientAdapter {
DefaultHttpClientAdapter _adapter = DefaultHttpClientAdapter();
#override
void close({bool force = false}) {
_adapter.close(force: force);
}
#override
Future<ResponseBody> fetch(RequestOptions options,
Stream<List<int>> requestStream, Future<dynamic> cancelFuture) async {
String url = options.uri.toString();
if (url.contains(URLS.IP_ADDRESS) && await AuthUtils.isLoggedIn()) {
options.followRedirects = false;
options.headers.addAll({"Authorization": await AuthUtils.getJwtToken()});
}
final response = await _adapter.fetch(options, requestStream, cancelFuture);
if (response.statusCode == 302 || response.statusCode == 307) {
String redirect = (response.headers["location"][0]);
if(!redirect.contains(URLS.IP_ADDRESS)) {
options.path = redirect;
options.headers.clear();
}
return await fetch(options, requestStream, cancelFuture);
}
return response;
}
}
I disallowed following redirects.
Used the response object to check if it was redirected.
If it was 302, or 307, (HTTP Redirect Codes), I resent the request after clearing the Auth Headers.
I used an additioal check to send the headers only if the path contained my specific domain URL (or IP Address in this example).
All of the above, using a CustomHttpAdapter in Dio. Can also be used for images, by changing the ResponseType to bytes.
Let me know if this helps you!
I was using django restframework. I applied Token authentication in REST API. I use to pass token in request header (used ModHeader extension of Browser which automatically put Token in Authorization of request header) of django API till here every thing was fine.
But while making a click on Images/Files (which now shows the s3 URL). The Authorization automatically get passed. Thus the issue.
Link look similar to this.
https://.s3.amazonaws.com/media//small_image.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=XXXXXXXXXXXXXXXXXXXXX%2F20210317%2Fap-south-XXXXXXXXFaws4_request&X-Amz-Date=XXXXXXXXXXXXXXX&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
I lock the ModHeader extension to pass Authorization Token only while making rest to REST API and not while making resquest to S3 resources. i.e. do not pass any other Authorization while making request to S3 resource.
It's a silly mistake. But in case it helps.
Flutter: if you experience this with the http dart package, then upgrade to Flutter v2.10!
Related bugs in dart issue tracker:
https://github.com/dart-lang/sdk/issues/47246
https://github.com/dart-lang/sdk/issues/45410
--> these has been fixed in dart 2.16, which has been shipped with Flutter v2.10!
https://medium.com/dartlang/dart-2-16-improved-tooling-and-platform-handling-dd87abd6bad1

Unable to download a document from google cloud storage

I am able to upload a document and download the document from google cloud storage for signed url using httpclient in java.But,when i put the same signed url in browser i am unable to download document for the link.I am getting following error
The request signature we calculated does not match the signature you
provided. Check your Google secret key and signing method.`
But when i mark check shared publicly check box in storage browser i am able to download from the generated signed url.But i want to allow a user to download a document from the browser without marking it as shared publicly.
.
I want to get confirm on some confusing part like
For document to get accessible by user who does not have google account after creating a signed url also i have to check shared publicly check box in storage browser?
But i think if the url is signed then it should not be check for shared publicly checkbox and user who does not have google account can access the document?But in my case it is not happening .According to link
https://developers.google.com/storage/docs/accesscontrol#About-CanonicalExtensionHeaders
it talks about Canonicalized_Extension_Headers .So i put in my request header
request.addHeader("x-goog-acl","public-read");
This is my code
// construct URL
String url = "https://storage.googleapis.com/" + bucket + filename +
"?GoogleAccessId=" + GOOGLE_ACCESS_ID +
"&Expires=" + expiration +
"&Signature=" + URLEncoder.encode(signature, "UTF-8");
System.out.println(url);
HttpClient client = new DefaultHttpClient();
HttpPut request = new HttpPut(url);
request.addHeader("Content-Type", contentType);
request.addHeader("x-goog-acl","public-read");// when i put this i get error
request.addHeader("Authorization","OAuth 1/zVNpoQNsOSxZKqOZgckhpQ");
request.setEntity(new ByteArrayEntity(data));
HttpResponse response = client.execute(request);
When i put request.addHeader("x-goog-acl","public-read");i get error
HTTP/1.1 403 Forbidden error .
.But when i remove this line it is uploaded successfully .It seems like i need to set
request.addHeader("x-goog-acl","public-read") to make it publicly accessible but on putting this on my code i am getting error.
.Any suggestion Please?
Finally Solved it.
To run singed url from browser you have to set HTTP header . In https://developers.google.com/storage/docs/accesscontrol#Construct-the-String
Content_Type Optional. If you provide this value the client (browser) must provide this HTTP header set to the same value.There is a word most.
So if you are providing Content_Type for sign string you must provide same Content_Type in browser http header.When i set Content_Type in browser header this error finally solved
this works for me:
set_include_path("../src/" . PATH_SEPARATOR . get_include_path());
require_once 'Google/Client.php';
function signed_storageURL($filename, $bucket, $p12_certificate_path, $access_id, $method = 'GET', $duration = 3600 )
{
$expires = time( ) + $duration*60;
$content_type = ($method == 'PUT') ? 'application/x-www-form-urlencoded' : '';
$to_sign = ($method."\n"."\n".$content_type."\n".$expires."\n".'/'.$bucket.'/'.$filename);
$signature = '';
$signer = new Google_Signer_P12(file_get_contents($p12_certificate_path), 'notasecret');
$signature = $signer->sign($to_sign);
$signature = urlencode( base64_encode( $signature ) );
return ('https://'.$bucket.'.commondatastorage.googleapis.com/'.$filename.'?GoogleAccessId='.$access_id.'&Expires='.$expires.'&Signature='.$signature);
}
$url = signed_storageURL(rawurlencode("áéíóú espaço & test - =.jpg"),'mybucket', 'mykey.p12','myaccount#developer.gserviceaccount.com');
echo ''.$url.'';

Resources