url with % doesn't get to api - javascript

Hi trying to get a signUrl from S3, for some reason making the call with % isn't parse correctly by my code. I get a 404 not found.
This is the ajax request:
https://stage.musicmarkers.com/website/api/admin/get-signed-url/thumbnail/magazine%2F2BE.gif/image%2Fgif
My API:
app.get('/website/api/admin/get-signed-url/thumbnail/:key/:type', auth.getMember, directives.noCache, getThumbnailSingedUrl);
My function:
function getThumbnailSingedUrl(req, res) {
if (!isAdmin(req, res)) {
return;
}
var key = req.params.key || '';
var type = req.params.type || '';
ThumbnailBucketFacade.getSignedUrl(
'putObject',
key,
type,
function onGotSignedUrl(error, result) {
if (error) {
RestResponse.serverError(res, error);
} else {
RestResponse.ok(res, result);
}
}
);
}
Making the call in a dev environment works.
Making the call without % environment works.
Same code exactly in a different project works.
Any ideas?

I believe what you have is encoded URI. So you need to decode it before using it:
const key = req.params.key && decodeURIComponent(req.params.key) || '';
const type = req.params.type && decodeURIComponent(req.params.type) || '';
More on decoreURIComponent here.
This is also backward compatible, so you don't have to worry that a plain string will get mangled.

So eventually it was a configuration issue at 'nginx', the 'nginx' router
was configured to add '/' at the end of the site name. That made all the
other slashes scrambled and ultimately to the call not to be recognise.
Thank's for those helping.

Related

pdf.js downloading as document.pdf instead of filename

I am using pdf.js library in my application.
It has integrated really well except for when i am trying to download the document. Everytime i download a specific file it gets downloaded as document.pdf
I have quite a lot of files to download and this is creating a bit of confusion.
My code goes as below:
<iframe src="pdf_viewer/web/viewer.html?file=/docs/resumes/1b763820-e262-4f76-8502-8872a3cb52e8&filename=sample.pdf"></iframe>
my first parameter is the file id and the second parameter is the name with which the document should be downloaded as.
Below code is the one present in the pdf viewer viewer.js file
function getPDFFileNameFromURL(url) {
var defaultFilename = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'document.pdf';
console.log(url);
console.log(defaultFilename);
if (isDataSchema(url)) {
console.warn('getPDFFileNameFromURL: ' + 'ignoring "data:" URL for performance reasons.');
return defaultFilename;
}
var reURI = /^(?:(?:[^:]+:)?\/\/[^\/]+)?([^?#]*)(\?[^#]*)?(#.*)?$/;
var reFilename = /[^\/?#=]+\.pdf\b(?!.*\.pdf\b)/i;
var splitURI = reURI.exec(url);
var suggestedFilename = reFilename.exec(splitURI[1]) || reFilename.exec(splitURI[2]) || reFilename.exec(splitURI[3]);
if (suggestedFilename) {
suggestedFilename = suggestedFilename[0];
if (suggestedFilename.indexOf('%') !== -1) {
try {
suggestedFilename = reFilename.exec(decodeURIComponent(suggestedFilename))[0];
} catch (ex) {}
}
}
return suggestedFilename || defaultFilename;
}
From my understanding of the code, what i am doing regarding the input is right. Where could i be going wrong ?
i figured out the solution
<iframe src="pdf_viewer/web/viewer.html?file=/docs/resumes/1b763820-e262-4f76-8502-8872a3cb52e8?sample.pdf"></iframe>
This takes the input in the url, now i can extract filename from the url

Getting textbox values from a CefSharp browser using javascript

I've got a winforms app that has a ChromiumWebBrowser control and some basic windows controls. I want to be able to click a button, call javascript to get the value of a textbox in the browser, and copy the returned value to a textbox in the winforms app. Here is my code:
string script = "(function() {return document.getElementById('Email');})();";
string returnValue = "";
var task = browser.EvaluateScriptAsync(script, new { });
await task.ContinueWith(t =>
{
if (!t.IsFaulted)
{
var response = t.Result;
if (response.Success && response.Result != null)
{
returnValue = (string)response.Result;
}
}
});
txtTarget.Text = returnValue;
The result that comes back however is just "{ }". I've loaded the same web page in Chrome and executed the same javascript in the dev tools and I get the textbox value as expected.
The demo I looked at had sample code, simply "return 1+1;", and when I tried that I was getting the value "2" returned instead of "{ }". Interestingly, when I tried
string script = "(function() {return 'hello';})()";
I was still getting "{ }", almost as though this doesn't work with strings.
I've been scratching my head at this for a while and haven't been able to figure out how to solve this. Am I making a very basic syntax error or is there something more complicated going on?
So I think I've figured it out:
string script = "(function() {return document.getElementById('Email').value;})();";
string returnValue = "";
var task = browser.EvaluateScriptAsync(script);
await task.ContinueWith(t =>
{
if (!t.IsFaulted)
{
var response = t.Result;
if (response.Success && response.Result != null)
{
returnValue = response.Result.ToString();
}
}
});
txtTarget.Text = returnValue;
Removing the args object from EvaluateScriptAsync seemed to fix the issue. Not sure what the problem was - perhaps it was trying to run the javascript function with an empty args object when it shouldn't take any parameters?
Either way, it's resolved now.
public void SetElementValueById(ChromiumWebBrowser myCwb, string eltId, string setValue)
{
string script = string.Format("(function() {{document.getElementById('{0}').value='{1}';}})()", eltId, setValue);
myCwb.ExecuteScriptAsync(script);
}
public string GetElementValueById(ChromiumWebBrowser myCwb, string eltId)
{
string script = string.Format("(function() {{return document.getElementById('{0}').value;}})();",
eltId);
JavascriptResponse jr = myCwb.EvaluateScriptAsync(script).Result;
return jr.Result.ToString();
}

Always Pass Post variable in $http.post

I have about 70 of these in my angularjs code. About 65 of them send the authtoken variable through.
$http.post("/url", { name: $scope.name, authtoken:localStorage['authtoken']});
I remember seeing somewhere that it might be beneficial to make it so it passes authtoken as a default through all my $http.post calls so I don't have to type it in every time.
Is this a good idea? If so, does anyone know how I would accomplish it? Just looking for some insight and getting pushed in the right direction.
You can use Interceptors like this:
angular.module('app').config(function($httpProvider) {
$httpProvider.interceptors.push(function() {
return {
request: function(req) {
if(req.method.toUpperCase() === 'POST') {
if(typeof req.data === 'object') {
req.data = req.data || {};// typeof Null is 'object' since the beginning of JavaScript
req.data['authtoken'] = localStorage['authtoken'];
} else {
req.data += '&authtoken='+localStorage['authtoken']
}
}
return req;
}
};
}
});
I hope this will help you.
Consider use of jQuery.ajaxSetup() here is API https://api.jquery.com/jQuery.ajaxSetup/
You can set up ajax global handler ajaxStar (https://api.jquery.com/ajaxStart/)
and modify the passed data by adding your authtoken.
Here is good article nearly about http://weblogs.asp.net/hajan/simplify-your-ajax-code-by-using-jquery-global-ajax-handlers-and-ajaxsetup-low-level-interface

Signature generation in Amazon S3 using Javascript

I am trying to send a PUT request to an Amazon compatible storage, and I keep getting the following error:
"<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your Secret Access Key and signing method. For more information, see REST Authentication and SOAP Authentication for details.</Message><RequestId>0af9f985:155f11613d1:1732:13</RequestId></Error>"
Can someone please tell me how to generate the correct signature using the Secret Access Key and other parameters, in Javascript. I know that I am using the correct credentials, because all other operations supported by Amazon S3 are working, using the Amazon S3 SDK. I went through this link:
http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html, but I couldn't find what the method is expecting for each parameters.
Adding the code, that I have written. This is pretty much the same as you see in the Javascript SDK, only the method canonicalizedResource, is more simpler:
private stringToSign(request: any) {
var parts = [];
parts.push(request.headers['method']);
parts.push(request.headers['Content-MD5'] || '');
parts.push(request.headers['Content-Type'] || '');
parts.push(request.headers['presigned-expires'] || '');
var headers = this.canonicalizedAmzHeaders(request);
if (headers) parts.push(headers);
parts.push(this.canonicalizedResource(request));
return parts.join('\n');;
}
private canonicalizedAmzHeaders(request: any) {
var amzHeaders = [];
AWS.util.each(request.headers, function(name) {
if (name.match(/^x-amz-/i))
amzHeaders.push(name);
});
amzHeaders.sort(function(a, b) {
return a.toLowerCase() < b.toLowerCase() ? -1 : 1;
});
var parts = [];
AWS.util.each(amzHeaders, function(name) {
parts.push(amzHeaders[name].toLowerCase() + ':' + request.headers[amzHeaders[name]]);
});
return parts.join('\n');
}
private canonicalizedResource(request) {
return request.path || '/';
}
I call the method like:
var signature = this.sign(AWS.config.credentials.secretAccessKey, this.stringToSign(request));
Can you make sure your system time is up to date? I have had issues when my system time is out of sync. AWS rejects those API calls.

How to extract partial JSON from API response?

Load when the browser is open
Thats my previous question related to this topic.
My problem is that the server api i use has added a new item to the list and as i stated in the previous question im not very skilled with API's or jQuery, therefore i would like to know what can you recomend me to read about this and also pratical solutions. I need to make it so the field that the js uses is only {"name":"Arthas","slug":"arthas","build":"12340","status":1} and not the rest.
Many thanks in advance.
This is the api -> http://api.neverendless-wow.com/server-status
{"servers":[{"name":"Arthas","slug":"arthas","build":"12340","status":1},{"name":"Deathwing","slug":"deathwing","build":"13623","status":1}],"alerts":[]}
This is my current js
function checkStatus()
{
jQuery.getJSON("http://api.neverendless-wow.com/server-status",function(data){
if (data.status == '1') {jQuery('#ServStat').addClass('online').removeClass('offline').attr('label','Online');}
else {jQuery('#ServStat').addClass('offline').removeClass('online').attr('label','Offline');}});
}
checkStatus();
{
setInterval(changeState, 300000)
}
You need to use data as array (data[0]) and hence your code will be as follows:
function checkStatus()
{
jQuery.getJSON("http://api.neverendless-wow.com/server-status",function(data){
if (data.servers[0].status == '1') {
jQuery('#ServStat').addClass('online').removeClass('offline').attr('label','Online');
}
else {
jQuery('#ServStat').addClass('offline').removeClass('online').attr('label','Offline');
}
});
}
checkStatus();
{
setInterval(changeState, 300000)
}
I would probably go with something like this:
// check server status
function checkStatus()
{
$.getJSON(server_url, function(data) {
// reset
var mode = "Offline";
$('.status').removeClass('online').addClass('offline');
// is available?
if (data !== null && data.servers !== null && data.servers[0].status === 1) {
mode = "Online";
$('.status').removeClass('offline').addClass('online');
}
// Extract data from received JSON string is exists
extractData(data);
// set needed attributes
$('.status')
.attr('label', mode)
.text('Servers are ' + mode);
});
}
Live demo available on JsBin

Categories