s3 "signature doesn't match" client side post jquery-file-upload - javascript

I am generating a signature for doing client side posting to s3 in node on the back end and submitting it via jquery-file-upload on the client. My signature generation looks like the following:
app.post('/api/v1/s3', function(req, res){
var data = utils.getReqJson(req.body);
var mime_type = mime.lookup(data.filename);
var expire = moment().utc().add('hour', 1).toJSON("YYYY-MM-DDTHH:mm:ss Z");
var policy = JSON.stringify({
"expiration": expire,
"conditions": [
{"bucket": aws_bucket},
["starts-with", "$key", aws_bucket_dir],
{"acl": "private"},
{"success_action_status": "201"},
["starts-with", "$Content-Type", ''],
["content-length-range", 0, max_filesize]
]
});
var base64policy = new Buffer(policy).toString('base64');
var signature = crypto.createHmac('sha1', process.env.AWS_SECRET).update(base64policy).digest('base64');
signature = encodeURIComponent(signature.trim());
signature = signature.replace('%2B','+');
var file_key = uuid.v4();
res.json({ policy: base64policy,
signature: signature,
key: aws_bucket_dir + file_key + "_" + data.filename,
contentType: mime_type,
aws_access: process.env.AWS_ACCESS_KEY,
bucket_dir: aws_bucket_dir,
bucket: aws_bucket
});
});
Then on the front end I have the following code:
this.$().fileupload({
dataType: 'json',
type: 'POST',
autoUpload: true,
add: function (e, data) {
$.ajax({
url: window.ENV.api_url+'/' + window.ENV.api_namespace + '/s3',
type: 'POST',
dataType: 'json',
data: {
"filename": data.files[0].name
},
async: false,
success: function(retdata) {
//do actual upload stuff now.
data.url = 'https://'+retdata.bucket+'.s3.amazonaws.com/';
data.formData = {
key: retdata.key,
AWSAccessKeyId: retdata.aws_access,
acl: 'private',
policy: retdata.policy,
signature: retdata.signature,
success_action_status: 201,
"Content-Type": retdata.contentType
};
data.submit()
.success(function (result, textStatus, jqXHR) {
console.log('Success: ' + result);
})
.error(function (jqXHR, textStatus, errorThrown) {
console.log('Error: ' + errorThrown);
console.log(jqXHR);
console.log('Status: ' + textStatus);
});
console.log(retdata);
},
error: function (xhr, ajaxOptions, thrownError) {
console.log('AJAX: ' + xhr);
console.log('AJAX: ' + thrownError);
}
});
},
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#progress .progress-bar').css(
'width',
progress + '%'
);
}
});
It seems as though I am submitting the correct form data to match my signature generation, but I am getting the following errors every time I try to submit:
SignatureDoesNotMatch - The request signature we calculated does not match the signature you provided. Check your key and signing method.
I am struggling to figure out what I might be doing wrong, if anyone can help I would appreciate it.

I struggled with this for a while and eventually got it working using the following:
in the s3 handler:
var uploadToS3 = function(s3Url, cb){
var fd = new FormData();
var file = document.getElementById('file').files[0];
var key = 'uploads\/' + file.name;
fd.append('key', 'uploads\/' + file.name);
fd.append('acl', 'public-read');
fd.append('Content-Type', 'multipart/form-data');
fd.append('AWSAccessKeyId', 'XXXX');
fd.append('policy', s3Url.s3Policy);
fd.append('signature', s3Url.s3Signature);
fd.append('file', file);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://XXXX.s3.amazonaws.com', true);
/////////////////////////////////////////////////////////
// Keep track of upload progress so that we can message//
// it to the user. //
/////////////////////////////////////////////////////////
var firstProgressEvent = true;
xhr.loaded = 0;
xhr.upload.addEventListener('progress', function(e) {
if (firstProgressEvent) {
firstProgressEvent = false;
}
xhr.loaded += (e.loaded - xhr.loaded);
$('progress').val((xhr.loaded / e.total) * 100);
}, false);
xhr.onreadystatechange = function(){
if ( xhr.readyState == 4 ) {
if ( xhr.status >= 200 && xhr.status < 400 ) {
cb(xhr.status);
} else {
cb(xhr.status);
}
}
};
xhr.onerror = function () {
error(xhr, xhr.status);
};
xhr.send(fd);
};
});
on the server:
createS3Policy = function(key, callback) {
var date = new Date();
var s3Policy = {
"expiration": new Date(Date.now() + 300000),
"conditions": [
{"bucket": "XXX"},
["starts-with", "$key", key],
{"acl": "public-read"},
["starts-with", "$Content-Type", "multipart/form-data"],
["content-length-range", 0, 524288000]
]
};
////////////////////////////////////
// stringify and encode the policy//
////////////////////////////////////
var stringPolicy = JSON.stringify(s3Policy);
var base64Policy = Buffer(stringPolicy, "utf8").toString("base64");
////////////////////////////////////
// sign the base64 encoded policy //
////////////////////////////////////
var signature = crypto.createHmac("sha1", process.env.AWS_SECRET_ACCESS_KEY)
.update(new Buffer(base64Policy, "utf8")).digest("base64");
////////////////////////////////////
// build the results object //
////////////////////////////////////
var s3Credentials = {
s3Policy: base64Policy,
s3Signature: signature
};
callback(s3Credentials);
};

Related

How to upload files & Get the public url Google Drive Api?

I create a simple website for Uploading files on Google Drive using Google Drive Api.
This is My Code :
$.ajax({
type: "POST",
beforeSend: function(request) {
request.setRequestHeader("Authorization", "Bearer" + " " + localStorage.getItem("accessToken"));
},
url: "https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart&fields=webViewLink",
data:{
uploadType:"media"
},
xhr: function () {
var myXhr = $.ajaxSettings.xhr();
if (myXhr.upload) {
myXhr.upload.addEventListener('progress', that.progressHandling, false);
}
return myXhr;
},
success: function (data) {
console.log(data);
},
error: function (error) {
console.log(error);
},
async: true,
data: formData,
cache: false,
contentType: false,
processData: false,
timeout: 60000
});
};
Upload.prototype.progressHandling = function (event) {
var percent = 0;
var position = event.loaded || event.position;
var total = event.total;
var progress_bar_id = "#progress-wrp";
if (event.lengthComputable) {
percent = Math.ceil(position / total * 100);
}
// update progressbars classes so it fits your code
$(progress_bar_id + " .progress-bar").css("width", +percent + "%");
$(progress_bar_id + " .status").text(percent + "%");
};
$("#upload").on("click", function (e) {
var file = $("#files")[0].files[0];
var upload = new Upload(file);
// maby check size or type here with upload.getSize() and upload.getType()
// execute upload
upload.doUpload();
});
});
Everything is Oky, But I just want to get the public URL of The files 😭 I just want to show the public url after file uploaded. Help Me Please
after upload the file and getting the fileId:
async function generatePublicUrl(fileId) {
try {
await drive.permissions.create({
fileId: fileId,
requestBody: {
role: "reader",
type: "anyone",
},
});
const result = await drive.files.get({
fileId: fileId,
fields: "webViewLink, webContentLink",
});
return result;
} catch (err) {
console.log(err);
}
}
and after doing that you just put your fileId in the format:
https://drive.google.com/file/d/"yourfileId"/preview
The Google Drive api does not have a method for creating the sharable link.
You will need to manually go to the Google drive website and create your sharable link there and store it in your system.

Prometheus Pushgateway from Browser JS/AJAX

I am searching for an example on how to push metric to the pushgateway via ajax.
echo 'some_metric 42' | curl --user user:pass --data-binary #- https://example.com/metrics/job/author_monitoring/jobname/count_open
with curl it works perfect!
I don't know how to translate this in js/jquery.
Maybe someone has an example
Here is what I got so far.
(function ($, $document) {
"use strict";
function textToBin(text) {
return (
Array
.from(text)
.reduce((acc, char) => acc.concat(char.charCodeAt().toString(2)), [])
.map(bin => '0'.repeat(8 - bin.length) + bin)
.join(' ')
);
}
var username = "user";
var password = "pass";
var metric = 'some_metric 42';
var binaryData = textToBin(metric);
$.ajax({
url: "https://example.com/metrics/job/author_monitoring/jobname/count_open",
data: binaryData,
type: 'POST',
crossDomain: true,
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
},
success: function () {
console.log("Success");
},
error: function () {
console.log('Failed!');
}
});
})($, $(document));
here is the error:
text format parsing error in line 1: invalid metric name
okay I got it.
There is an easy solution, import is the \n at the end of the string.
(function ($, $document) {
"use strict";
var username = "user";
var password = "pass";
var metric = 'some_metric 42\n';
$.ajax({
url: "https://example.com/metrics/job/author_monitoring/jobname/count_open",
data: metric,
type: 'POST',
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
xhr.setRequestHeader("Content-Type", "text/plain");
},
success: function () {
console.log("Success");
},
error: function () {
console.log('Failed!');
}
});
})($, $(document));

Progress in ajax while uploading 2 files or more

Hi Im trying to upload a 2 file or more, my problem is my progress bar will say 100% because of the small file being uploaded first, then its going back to the percent of the large file.. My question is how can I have a same progress if i have many files being uploaded?
for (var i = 0, f; f = files.files[i]; i++) {
$.ajax({
xhr: function(){
//upload Progress
var xhr = $.ajaxSettings.xhr();
if (xhr.upload) {
xhr.upload.addEventListener('progress', function(event) {
var percent = 0;
var position = event.loaded || event.position;
var total = event.total;
if (event.lengthComputable) {
percent = Math.ceil(position / total * 100);
}
//update progressbar
$('.bar').width(percent + '%');
}, true);
}
return xhr;
},
url: 'https://content.dropboxapi.com/2/files/upload',
type: 'post',
data: f,
processData: false,
contentType: 'application/octet-stream',
headers: {
"Authorization": "Bearer ACCESS TOKEN",
"Dropbox-API-Arg": '{"path": "/'+f.name+'", "mode": "add","autorename": true,"mute": false}'
},
success: function (data) {
console.log(data);
app.alert.show('success-message', {
level: 'success',
messages: 'your file has been upload to Dropbox',
autoClose: true
});
},
error: function (data) {
console.log(data);
}
})
}
I think you should store progress of each file in different variable (or maybe array of variables) and write function, that will update progressbar width when this vars are changed.

how to use PostgreSQL mod for vertx in js?

hi im new in vertx and i want use https://github.com/vert-x/mod-mysql-postgresql for a service
i use this code for my web server
var vertx = require('vertx');
var console = require('vertx/console');
var Server = vertx.createHttpServer();
Server.requestHandler(function (req) {
var file = req.path() === '/' ? 'index.html' : req.path();
if (file === '/foo') {
foo(req);
}
else{
req.response.sendFile('html/' + file);
}
}).listen(8081);
function foo(req) {
req.bodyHandler(function (data) {
//data is json {name:foo, age:13} i want insert this in any table in postgre
//do
var dataresponse= messagefrompostgre;//e: {status:"ok", code:200, message: "its ok"}
req.response.putHeader("Content-Type", "application/json");
req.response.end(dataresponse);
});
}
and this is my event click button
$.ajax({
data: {name:foo, age:13} ,
url: '/foo',
type: 'post',
dataType: 'json',
complete: function (response) {
alert(JSON.stringify(response));
}
});
I found how to do it:
var vertx = require('vertx');
var console = require('vertx/console');//TODO: remove
var eventBus = vertx.eventBus;
var Server = vertx.createHttpServer();
Server.requestHandler(function (req) {
var file = req.path() === '/' ? 'index.html' : req.path();
if (file === '/foo') {
foo(req);
}
else{
req.response.sendFile('html/' + file);
}
}).listen(8081);
function foo(req) {
req.bodyHandler(function (data) {
//data is json {name:foo, age:13}
var jsona={
"action" : "raw",
"command" : "select * from test"
}
eventBus.send("PostgreSQL-asyncdb",jsona, function(reply) {
req.response.putHeader("Content-Type", "application/json");
req.response.end(JSON.stringify(reply));
});
});
}
and this return:
{"message":"SELECT 6","rows":6,"fields":["testt"],"results":[["lol"],["lolŕ"],["lol2"],["lol2"],["testlol"],["testlolp"]],"status":"ok"}

Reactive http requests in JavaScript

Sorry for my English. I made some test client for test our web server, but I am unhappy with my work. Please help me improve my code.
I want to make serial HTTP requests. I have Array with test requests:
Aua.Queries = ko.observableArray([
new Query("/srv?key=value&key2=someValue", 300, "comment for this request"),
new Query("/srv?someKey=SomeValue", 0, "comment for this request")
]);
(in Aua.Queries array 24 queries)
My wrapper for Aua.Queries observableArray:
function Query(query, result, comment) {
var me = this;
me.Query = "http://mydomain.com?" + query;
me.Result = result;
me.Comment = comment;
me.Selected = ko.observable(false);
}
When click send handler, I do this:
Aua.SendHandler = function () {
Aua.Loading(true);
Aua.Responses([]);
if (Aua.Advanced() == true) {
var queries = Aua.Queries();
console.log("Selected Request Count: ",
Enumerable.From(queries).Where("$.Selected() == true").Select(function(query) {
console.log("Result: ", query.Result);
Aua.Url(query.Query);
query.Selected(false);
sendRequest();
}).Count());
}
else if (Aua.RequestCount() > 1) {
for (var i = Aua.RequestCount(); i > 0; i--) {
Aua.RequestCount(i);
setUrlByStatus();
sendRequest();
}
}
else
sendRequest();
};
And sendRequest Handler:
function sendRequest() {
console.log("Sending request to: ", Aua.Url());
$.ajax(Aua.Url(), {
dataType: 'text',
cache: false,
type: 'GET',
success: function(data, status, xhr) {
Aua.Responses.push({
"Data": data,
"Status": xhr.status + " " + xhr.statusText
});
prettyPrint();
},
error: function(xhr, status, data) {
Aua.Responses.push({
"Data": data,
"Status": xhr.status + " " + xhr.statusText
});
prettyPrint();
console.log("Error: ", Aua.Responses());
},
complete: function() {
Aua.Loading(false);
}
});
}
Set type of request format.
function setUrlByStatus() {
if (Aua.RequestStatus() === "error")
Aua.Url(Aua.Queries()[Math.floor(Math.random() * Aua.Queries().length)].Query);
else
Aua.Url(
"http://mydomain.com?" +
"action=" + Aua.Action() +
"&number=" + Aua.Number());
}
A have 3 types of sending request.
Send multiple request from Aua.Queries array.
Send requests by depent in count.
And Send 1 request in input.
I do my self.
And i learned how organaize my code
/*
Client requests for tes our server
Make different demands on the Serer.
Query setings:
     Send something that is in the input.
     Send to a specified number of times queries and allow the user to choose what kind of answer he wants, success or error.
         For successful actions are random data request: email, account, paper.
     Send requests from the table.
     All the answers to print. Prettify XML response.
     After the data to make a progress report
         The following table show: Status Code, Comments, Quantity.
     HTTP status display for each response received and paint the fatal errors in red.
*/
(function (global, undefined) {
function ajaxObject(url, query, response, loading) {
console.log("Query: ", query());
var catched = query();
return $.ajax({
cache: false,
dataType: "text",
type: "GET",
url: url() + catched,
success: function (data, status, xhr) {
response.push({
Data: data,
Query: catched,
Status: xhr.status + ' ' + xhr.statusText
});
},
error: function (xhr, status, data) {
response.push({
Data: data,
Query: catched,
Status: xhr.status + " " + xhr.statusText
});
},
complete: function () {
loading(false);
prettyPrint();
}
});
}
function Query(query, result, comment) {
var me = this;
me.Query = query;
me.Result = result;
me.Comment = comment;
me.Selected = ko.observable(false);
me.Describtion = ko.observable(comment);
me.DescribtionComment = function (data) { me.Describtion(data.Comment); };
me.DescribtionQuery = function (data) { me.Describtion(data.Query); };
}
var queries = [
new Query("/zibaba?paper=go&id=1&account=someacc&date=20130221174323", 453, "Error. Expected parameter test"),
new Query("/zibaba?paper=go&account=someacc", 0, "Expected parameter test"),
new Query("/zibaba?paper=do&id=3&account=someacc&date=20130221174323", 1, " Forbidden"))
];
var Aua = global.Aua = new function Aua() { };
Aua.Configuration = {
Advanced: {
Queries: queries,
QueriesSelectAll: ko.observable(false),
Toggle: ko.observable(false)
},
Counter: ko.observable(1),
Query: ko.observable(),
Url: ko.observable(),
Status: ko.observable("success")
};
Aua.Configuration.Advanced.QueriesSelectAll.subscribe(function () {
var qs = Aua.Configuration.Advanced.Queries;
for (var i = 0; i < qs.length; i++)
qs[i].Selected(!qs[i].Selected());
});
Aua.IsLoading = ko.observable(false);
Aua.SendHandler = function() {
Aua.IsLoading(true);
Aua.Responses([]);
if (Aua.Configuration.Advanced.Toggle() === true) {
$.when(Enumerable.From(Aua.Configuration.Advanced.Queries)
.Where("$.Selected() === true")
.Select(function(current) {
Aua.Configuration.Query(current.Query);
return ajaxObject(Aua.Configuration.Url, Aua.Configuration.Query, Aua.Responses, Aua.IsLoading);
}).ToArray());
} else {
$.when(Enumerable.Generate(function() {
var papers;
if (Aua.Configuration.Status() == "success") {
papers = ["do", "go"];
Aua.Configuration.Query(
"?account=" + Math.floor(Math.random() * 1234567 + 1) +
("&paper=" + papers[Math.floor(Math.random() * papers.length)]) +
("&id=" + Math.floor(Math.random() * 123754 + 1)));
} else if (Aua.Configuration.Status() == "error") {
papers = ["do", "go", "justdoit"];
var accounts = [Math.floor(Math.random() * 1234567 + 1), " ", Math.floor(Math.random() * 4532 + 1)],
ids = [" ", (Math.floor(Math.random() * 123754 + 1)), (Math.floor(Math.random()))];
Aua.Configuration.Query(
"?account=" + accounts[Math.floor(Math.random() * accounts.length)] +
"&paper=" + (papers[Math.floor(Math.random() * papers.length)]) +
"&id=" + (ids[Math.floor(Math.random() * ids.length)]));
}
return ajaxObject(Aua.Configuration.Url, Aua.Configuration.Query, Aua.Responses, Aua.IsLoading);
}, Aua.Configuration.Counter()).ToArray());
}
};
Aua.ResetHandler = function () { location.reload(); };
Aua.Statistics = {
Code: ko.observable(0),
Comment: ko.observable(0),
Quantity: ko.observable(0)
};
Aua.Responses = ko.observableArray([{
Data: ko.observable(),
Status: ko.observable(-1)
}]);
Aua.Responses([]);
$(document).on("ready", function () {
ko.applyBindings(Aua);
});
})(window);
Sorry for my English

Categories

Resources