I'm generating a series of variables in a loop (using JS), and I'm assigning them an .id and a .name based on the current index. At each loop I'm sending a request to the server using jQuery.post()method, but the returning response is just an empty variable.
Here's the code:
JavaScript
for ( var index = 0; index < 5; index++ ) {
var myVar = document.createElement('p');
myVar.id = 'myVarID' + index;
myVar.name = 'myVarName' + index;
//Send request to server
$(document).ready(function(){
var data = {};
var i = 'ind';
var id = myVar.id;
var name = myVar.name;
data[id] = name;
data[i] = index;
$.post("script.php", data, function(data){
console.log("Server response:", data);
});
});
}
PHP
<?php
$index = $_POST['ind'];
$myVar = $_POST['myVarID'.$index];
echo $myVar;
?>
Response: Server response: ''
If I instead set a static index in JS code, getting rid of the loop, so for example:
var index = 0;
I get the expected result: Server response: myVarName0
Why is this happening? And how can I solve it?
Assuming the php file is in order. I use this:
function doThing(url) {
getRequest(
url,
doMe,
null
);
}
function doMe(responseText) {
var container = document.getElementById('hahaha');
container.innerHTML = responseText;
}
function getRequest(url, success, error) {
var req = false;
try{
// most browsers
req = new XMLHttpRequest();
} catch (e){
// IE
try{
req = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
// try an older version
try{
req = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e){
return false;
}
}
}
if (!req) return false;
if (typeof success != 'function') success = function () {};
if (typeof error!= 'function') error = function () {};
req.onreadystatechange = function(){
if(req .readyState == 4){
return req.status === 200 ?
success(req.responseText) : error(req.status)
;
}
}
var thing = "script.php?" + url;
req.open("GET", thing, true);
req.send(null);
return req;
}
then use it like this:
doThing("myVarID="+myVar.id+"&i="+index);
also, you will have to change your PHP to something like this:
<?php
$index = $_GET['ind'];
$myVar = $_GET['myVarID'.$index];
echo $myVar;
?>
Obviously this code needs to be edited to suit your own needs
the function doMe is what to do when the webpage responds, in that example I changed the element with the id hahaha to the response text.
This won't win you any prizes but it'll get the job done.
Solution
It is working fine removing:
$(document).ready()
Working code
for ( var index = 0; index < 5; index++ ) {
var myVar = document.createElement('p');
myVar.id = 'myVarID' + index;
myVar.name = 'myVarName' + index;
//Send request to server
var data = {};
var i = 'ind';
var id = myVar.id;
var name = myVar.name;
data[id] = name;
data[i] = index;
$.post("script.php", data, function(data){
console.log("Server response:", data);
});
}
I'm trying to parse JSON I recieved from an API call, but I keep running into the error "TypeError: Cannot read property "id" from undefined. (line 42, file "")" I'm relatively new to Apps Script. Any ideas on what's going on? I can get the payload back in JSON, but can't seem to parse it.
function getInfo() {
var url = "https://subdomain.chargify.com/subscriptions.json";
var username = "xxx"
var password = "x"
var headers = {
"Authorization": "Basic " + Utilities.base64Encode(username + ':' + password)
};
var options = {
"method": "GET",
"contentType": "application/json",
"headers": headers
};
var response = UrlFetchApp.fetch(url, options);
var data = JSON.parse(response.getContentText());
Logger.log(data);
var id = data.subscription; // kicks back an error
// var id = data; works and returns the whole JSON payload
var ss = SpreadsheetApp.getActiveSheet()
var targetCell = ss.setActiveSelection("A1");
targetCell.setValue(id);
}
According to the documentation here
https://docs.chargify.com/api-subscriptions#api-usage-json-subscriptions-list
it returns an array of subscriptions when you call the /subscriptions.json endpoint. So probably your data object should be handled like:
for (var i=0;i<data.length;i++) {
var item = data[i]; //subscription object, where item.subscription probably works
Logger.log(JSON.stringify(item));
}
function getInfo() {
var url = "https://subdomain.chargify.com/subscriptions.json";
var username = "xxx"
var password = "x"
var headers = {
"Authorization": "Basic " + Utilities.base64Encode(username + ':' + password)
};
var options = {
"method": "GET",
"contentType": "application/json",
"headers": headers
};
var response = UrlFetchApp.fetch(url, options);
var data = JSON.parse(response.getContentText());
for (var i = 0; i < data.length; i++) {
var item = data[i]; //subscription object, where item.subscription probably works
Logger.log(JSON.stringify(item));
var subscriptionid = item.subscription.id;
}
var ss = SpreadsheetApp.getActiveSheet()
var targetCell = ss.setActiveSelection("A2");
targetCell.setValue(subscriptionid);
}
Moving a topic from google groups to here so it can help someone who is asking.
imageshack api: http://api.imageshack.us/
the final http reqeust is returning json:
{"success":true,"process_time":325,"result":{"max_filesize":5242880,"space_limit":52428800,"space_used":0,"space_left":52428800,"passed":0,"failed":0,"total":0,"images":[]}}
which is not good, as it didn't upload :(
it should return an image object. http://api.imageshack.us/#h.ws82a1l6pp9g
as this is what the upload image section on the imageshack api says
please help :(
my extension code
var blobUrl;
var makeBlob = function () {
bigcanvas.toBlob(function (blob) {
var reader = new window.FileReader();
reader.readAsBinaryString(blob);
reader.onloadend = function () {
blobBinaryString = reader.result;
blobUrl = blobBinaryString;
Cu.reportError(blobUrl);
uploadBlob();
}
});
};
var uploadedImageUrl;
var uploadBlob = function () {
HTTP('POST', 'https://api.imageshack.us/v1/images', {
contentType: 'application/x-www-form-urlencoded',
//'album=' + urlencode('Stock History') + '&
body: 'auth_token=' + urlencode(auth_token) + 'file#=' + blobUrl,
onSuccess: function (status, responseXML, responseText, headers, statusText) {
Cu.reportError('XMLHttpRequest SUCCESS - imageshack uploadBlob\n' + statusText + '\n' + responseText);
eval('var json = ' + responseText);
uploadedImageUrl = json.direct_link;
submitBamdex();
},
onFailure: function (status, responseXML, responseText, headers, statusText) {
Cu.reportError('XMLHttpRequest FAILLLLLLLL - imageshack uploadBlob\n' + statusText + '\n' + responseText);
}
});
};
makeBlob(); //callllll the func
What worked for me was reading about
the differences between URI's, files, blobs and Base64's in this article: https://yaz.in/p/blobs-files-and-data-uris/ .
fetching a new blob: https://masteringjs.io/tutorials/axios/form-data
and much more closed tabs along the way
so in my react component onChange handler I use new FileReader to read event.target.files[0], readAsDataURL(file), and set the Base64 encoded string to state.
I conditionally render an img src={base64stringfromState} to offer confirmation of correct image, then onSubmit, I convert this "Data URI" (the Base64 string), to a blob with one of these two codes I found somewhere (didn't end up using the first one but this is useful af and took forever to find):
const dataURItoBlob = (dataURI) => {
// convert base64/URLEncoded data component to raw binary data held in a string
var byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0)
byteString = atob(dataURI.split(',')[1]);
else
byteString = unescape(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to a typed array
var ia = new Uint8Array(byteString.length);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ia], {type:mimeString});
}
And
const blob = await fetch(base64imageString).then(res => res.blob())
Instead of all that shit we can just do this fetch a new version of the image or whatever and blob it right there, in the middle of constructing our photo upload/request :
event.preventDefault()
const blob = await fetch(base64stringfromState).then(res => res.blob())
const formData = new FormData()
formData.append('file#', blob)
formData.append('api_key', 'XXXXX')
formData.append('auth_token', 'XXXXXXXXXX')
formData.append('album', 'youralbumname')
const res = await axios.post('https://api.imageshack.com/v2/images', formData, {headers{'Content-Type':'multipart/form-data'}})
then all we have to do to store the uploaded image is to append https:// to and record the returned direct link for storage alongside its id so you can delete it if you need to later. Per the code earlier they spit out at
res.data.result.images[0].direct_link
res.data.result.images[0].id
This was a bitch to solve so hopefully this helps someone else with uploading photos to imageshack api cuz it's potentially a great value considering the limits of the competitors.
this code uploads a drawing on a canvas to imageshack
Can copy paste but have to update some things:
update username
update password
uploads drawing from canvas with id "bigcanvas"
update your API key
...
//this code uploads a drawing on a canvas to imageshack
var auth_token;
var loginImageshack = function() {
HTTP('POST','https://api.imageshack.us/v1/user/login',{
contentType: 'application/x-www-form-urlencoded',
body: 'user=USERNAME_TO_IMAGESHACK_HERE&password=' + urlencode('PASSWORD_TO_USERNAME_FOR_IMAGESHACK_HERE'),
onSuccess: function(status, responseXML, responseText, headers, statusText) {
Cu.reportError('XMLHttpRequest SUCCESS - imageshack login\n' + statusText + '\n' + responseText);
eval('var json = ' + responseText);
auth_token = json.result.auth_token;
makeImageshackFile();
},
onFailure: function(status, responseXML, responseText, headers, statusText) {
Cu.reportError('XMLHttpRequest FAILLLLLLLL - imageshack login\n' + statusText + '\n' + responseText);
}
});
};
var uploadedImageUrl;
var makeImageshackFile = function() {
var fd = new window.FormData();
fd.append("api_key", 'A835WS6Bww584g3568efa2z9823uua5ceh0h6325'); //USE YOUR API KEY HERE
fd.append("auth_token", auth_token);
fd.append('album', 'Stock History');
fd.append('title', 'THE-title-you-want-showing-on-imageshack')
fd.append("file#", bigcanvas.mozGetAsFile("foo.png")); //bigcanvas is a canvas with the image drawn on it: var bigcanvas = document.querySelector('#bigcanvas');
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
switch (xhr.readyState) {
case 4:
if (xhr.status==0 || (xhr.status>=200 && xhr.status<300)) {
Cu.reportError('XHR SUCCESS - \n' + xhr.responseText);
eval('var json = ' + xhr.responseText);
//ensure it passed else redo it I didnt program in the redo thing yet
//succesful json == {"success":true,"process_time":1274,"result":{"max_filesize":5242880,"space_limit":52428800,"space_used":270802,"space_left":52157998,"passed":1,"failed":0,"total":1,"images":[{"id":1067955963,"server":703,"bucket":2397,"lp_hash":"jj9g5p","filename":"9g5.png","original_filename":"foo.png","direct_link":"imageshack.us\/a\/img703\/2397\/9g5.png","title":"082813 200AM PST","description":null,"tags":[""],"likes":0,"liked":false,"views":0,"comments_count":0,"comments_disabled":false,"filter":0,"filesize":1029,"creation_date":1377681549,"width":760,"height":1110,"public":true,"is_owner":true,"owner":{"username":"bamdex","avatar":{"server":0,"filename":null}},"next_images":[],"prev_images":[{"server":59,"filename":"06mm.png"},{"server":706,"filename":"a1fg.png"}],"related_images":[{"server":59,"filename":"06mm.png"},{"server":41,"filename":"xn9q.png"},{"server":22,"filename":"t20a.png"},{"server":547,"filename":"fipx.png"},{"server":10,"filename":"dg6b.png"},{"se
uploadedImageUrl = json.result.images[0].direct_link;
Cu.reportError('succesfully uploaded image');
} else {
Cu.reportError('XHR FAIL - \n' + xhr.responseText);
}
break;
default:
//blah
}
}
xhr.open("POST", "https://api.imageshack.us/v1/images");
xhr.send(fd);
}
loginImageshack();
important note for code above
should use JSON.parse instead of eval if you want to submit the addon to AMO
should also probably change from using window to Services.appShel.hiddenDOMWindow so like new window.FormData(); would become new Services.appShel.hiddenDOMWindow.FormData(); OR var formData = Components.classes["#mozilla.org/files/formdata;1"].createInstance(Components.interfaces.nsIDOMFormData); OR Cu.import('resource://gre/modules/FormData.jsm')
helper functions required for the code above:
const {classes: Cc, interfaces: Ci, utils: Cu, Components: components} = Components
Cu.import('resource://gre/modules/Services.jsm');
...
function urlencode(str) {
return escape(str).replace(/\+/g,'%2B').replace(/%20/g, '+').replace(/\*/g, '%2A').replace(/\//g, '%2F').replace(/#/g, '%40');
};
...
//http request
const XMLHttpRequest = Cc["#mozilla.org/xmlextras/xmlhttprequest;1"];
/**
* The following keys can be sent:
* onSuccess (required) a function called when the response is 2xx
* onFailure a function called when the response is not 2xx
* username The username for basic auth
* password The password for basic auth
* overrideMimeType The mime type to use for non-XML response mime types
* timeout A timeout value in milliseconds for the response
* onTimeout A function to call if the request times out.
* body A string containing the entity body of the request
* contentType The content type of the entity body of the request
* headers A hash of optional headers
*/
function HTTP(method,url,options)
{
var requester = new XMLHttpRequest();
var timeout = null;
if (!options.synchronizedRequest) {
requester.onreadystatechange = function() {
switch (requester.readyState) {
case 0:
if (options.onUnsent) {
options.onUnsent(requester);
}
break;
case 1:
if (options.onOpened) {
options.onOpened(requester);
}
break;
case 2:
if (options.onHeaders) {
options.onHeaders(requester);
}
break;
case 3:
if (options.onLoading) {
options.onLoading(requester);
}
break;
case 4:
if (timeout) {
clearTimeout(timeout);
}
if (requester.status==0 || (requester.status>=200 && requester.status<300)) {
options.onSuccess(
requester.status,
requester.responseXML,
requester.responseText,
options.returnHeaders ? _HTTP_parseHeaders(requester.getAllResponseHeaders()) : null,
requester.statusText
);
} else {
if (options.onFailure) {
options.onFailure(
requester.status,
requester.responseXML,
requester.responseText,
options.returnHeaders ? _HTTP_parseHeaders(requester.getAllResponseHeaders()) : null,
requester.statusText
);
}
}
break;
}
}
}
if (options.overrideMimeType) {
requester.overrideMimeType(options.overrideMimeType);
}
if (options.username) {
requester.open(method,url,!options.synchronizedRequest,options.username,options.password);
} else {
requester.open(method,url,!options.synchronizedRequest);
}
if (options.timeout && !options.synchronizedRequest) {
timeout = setTimeout(
function() {
var callback = options.onTimeout ? options.onTimeout : options.onFailure;
callback(0,"Operation timeout.");
},
options.timeout
);
}
if (options.headers) {
for (var name in options.headers) {
requester.setRequestHeader(name,options.headers[name]);
}
}
if (options.sendAsBinary) {
Cu.reportError('sending as binary');
requester.sendAsBinary(options.body);
} else if (options.body) {
requester.setRequestHeader("Content-Type",options.contentType);
requester.send(options.body);
} else {
requester.send(null);
}
if (options.synchronizedRequest) {
if (requester.status==0 || (requester.status>=200 && requester.status<300)) {
options.onSuccess(
requester.status,
requester.responseXML,
requester.responseText,
options.returnHeaders ? _HTTP_parseHeaders(requester.getAllResponseHeaders()) : null,
requester.statusText
);
} else {
if (options.onFailure) {
options.onFailure(
requester.status,
requester.responseXML,
requester.responseText,
options.returnHeaders ? _HTTP_parseHeaders(requester.getAllResponseHeaders()) : null,
requester.statusText
);
}
}
return {
abort: function() {
}
};
} else {
return {
abort: function() {
clearTimeout(timeout);
requester.abort();
}
};
}
}
function _HTTP_parseHeaders(headerText)
{
var headers = {};
if (headerText) {
var eol = headerText.indexOf("\n");
while (eol>=0) {
var line = headerText.substring(0,eol);
headerText = headerText.substring(eol+1);
while (headerText.length>0 && !headerText.match(_HTTP_HEADER_NAME)) {
eol = headerText.indexOf("\n");
var nextLine = eol<0 ? headerText : headerText.substring(0,eol);
line = line+' '+nextLine;
headerText = eol<0 ? "" : headerText.substring(eol+1);
}
// Parse the name value pair
var colon = line.indexOf(':');
var name = line.substring(0,colon);
var value = line.substring(colon+1);
headers[name] = value;
eol = headerText.indexOf("\n");
}
if (headerText.length>0) {
var colon = headerText.indexOf(':');
var name = headerText.substring(0,colon);
var value = headerText.substring(colon+1);
headers[name] = value;
}
}
return headers;
}
is there any way how to get and parse signed_request in Node.js Facebook page tab app? I need to know page id and if user liked the page...
I did this a little while ago, and ended up writing a small library to do it. The original CoffeeScript can be found at https://gist.github.com/fbef51815ab6f062b51a#file_signed_request.coffee, here is a JavaScript translation:
var crypto = require('crypto');
SignedRequest = (function() {
function SignedRequest(secret, request) {
this.secret = secret;
this.request = request;
this.verify = this.verify.bind(this);
var parts = this.request.split('.');
this.encodedSignature = parts[0];
this.encoded = parts[1];
this.signature = this.base64decode(this.encodedSignature);
this.decoded = this.base64decode(this.encoded);
this.data = JSON.parse(this.decoded);
}
SignedRequest.prototype.verify = function() {
if (this.data.algorithm !== 'HMAC-SHA256') {
return false;
}
var hmac = crypto.createHmac('SHA256', this.secret);
hmac.update(this.encoded);
var result = hmac.digest('base64').replace(/\//g, '_').replace(/\+/g, '-').replace(/\=/g, '');
return result === this.encodedSignature;
};
SignedRequest.prototype.base64encode = function(data) {
return new Buffer(data, 'utf8').toString('base64').replace(/\//g, '_').replace(/\+/g, '-').replace(/\=/g, '');
};
SignedRequest.prototype.base64decode = function(data) {
while (data.length % 4 !== 0) {
data += '=';
}
data = data.replace(/-/g, '+').replace(/_/g, '/');
return new Buffer(data, 'base64').toString('utf-8');
};
return SignedRequest;
})();
module.exports = SignedRequest;
Which you can use like this:
var verifier = new SignedRequest(clientSecret, signedRequest);
verifier.verify() // whether or not the signed request verifies
verifier.data // the data from the signed request
I have this string in which i need to re-structure using JavaScript.
Label=11121212&TopicArn=test&AWSAccountId.member.1=YYYYYYY&ActionName.member.1=createTopic&Action=AddPermission&Version=2010-03-31&AWSAccessKeyId=XXXXXXXXX&SignatureVersion=2&SignatureMethod=HmacSHA1&Timestamp=2012-05-02T16%3A06%3A09.000Z&Signature=C3uIh%2Bz%2Fik
For this example, AWSAccessKeyId should be the first part of the string and label should be 2nd last. There are others as well, similar to this.
Expected output --AWSAccessKeyId=XXXXXXXXX&AWSAccountId.member.1=YYYYYYYYY&Action=AddPermission&ActionName.member.1=Publish&Label=ios-sns-permission-label&Signature=dEaNL0ibP5c7xyl4qXDPFPADW0meoUX9caKyUIx1wkk%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-05-02T00%3A51%3A23.965Z&TopicArn=arn%3Aaws%3Asns%3Aus-east-1%3A335750469596%3AiOSGoesWooooo-1335919882&Version=2010-03-31
Code that creates this incorrect string
exports.generatePayload = function(params, accessKeyId, secretKey, endpoint) {
var host = endpoint.replace(/.*:\/\//, "");
var payload = null;
var signer = new AWSV2Signer(accessKeyId, secretKey);
params = signer.sign(params, new Date(), {
"verb" : "POST",
"host" : host,
"uriPath" : "/"
});
var encodedParams = [];
for(var key in params) {
if(params[key] !== null) {
encodedParams.push(encodeURIComponent(key) + "=" + encodeURIComponent(params[key]));
} else {
encodedParams.push(encodeURIComponent(key));
}
}
payload = encodedParams.join("&");
return payload;
}
I tried putting this in an array and restructure it but it didn't work for me.
Please advice how this can be done easily using JavaScript
exports.generatePayload = function(params, accessKeyId, secretKey, endpoint) {
var host = endpoint.replace(/.*:\/\//, "");
var payload = null;
var signer = new AWSV2Signer(accessKeyId, secretKey);
params = signer.sign(params, new Date(), {
"verb" : "POST",
"host" : host,
"uriPath" : "/"
});
var encodedParams = [];
if(params["AWSAccessKeyId"] != null)
{
encodedParams.push(encodeURIComponent("AWSAccessKeyId") + "=" + encodeURIComponent(params["AWSAccessKeyId"]));
}
if(params["AWSAccountId.member.1"] != null)
{
encodedParams.push(encodeURIComponent("AWSAccountId.member.1") + "=" + encodeURIComponent(params["AWSAccountId.member.1"]));
}
//other_ifs_for_param_keys_here
payload = encodedParams.join("&");
return payload;