I'm trying to redirect the url of my app in node.js in this way:
// response comes from the http server
response.statusCode = 302;
response.setHeader("Location", "/page");
response.end();
But the current page is mixed with the new one, it looks strange :| My solution looked totally logical, I don't really know why this happens, but if I reload the page after the redirection it works.
Anyway what's the proper way to do HTTP redirects in node?
Looks like express does it pretty much the way you have. From what I can see the differences are that they push some body content and use an absolute url.
See the express response.redirect method:
https://github.com/visionmedia/express/blob/master/lib/response.js#L335
// Support text/{plain,html} by default
if (req.accepts('html')) {
body = '<p>' + http.STATUS_CODES[status] + '. Redirecting to ' + url + '</p>';
this.header('Content-Type', 'text/html');
} else {
body = http.STATUS_CODES[status] + '. Redirecting to ' + url;
this.header('Content-Type', 'text/plain');
}
// Respond
this.statusCode = status;
this.header('Location', url);
this.end(body);
};
server = http.createServer(
function(req, res)
{
url ="http://www.google.com";
body = "Goodbye cruel localhost";
res.writeHead(301, {
'Location': url,
'Content-Length': body.length,
'Content-Type': 'text/plain' });
res.end(body);
});
Yes it should be full url in setHeader.
res.statusCode = 302;
res.setHeader('Location', 'http://' + req.headers['host'] + ('/' !== req.url)? ( '/' + req.url) : '');
res.end();
What happens if you change it to 307 instead?
This issue may also depend on the type of request you are handling. A POST request cannot be redirected using the header. For example, a first-time visitor from to your app in FB will most-likely be coming via a "signed request" POST and therefore a redirect will not work.
Related
I'm trying to send an SMS via Twilio's API using an HTTP POST request that is called via server-side javascript in salesforce marketing cloud.
I can successfully send an SMS, the only problem is that accent characters (for instance ö, ü, à, è) are being omitted. So for instance if I send an SMS that should say "Dein persönlicher Rabatt", when I received the SMS, it says "Dein persnlicher Rabatt".
Here is my server-side javascript code:
`<script type="text/javascript" runat="server">
Platform.Load("core", "1");
var accountSid = [accountSid];
var authToken = [authToken];
var auth = Base64Encode(accountSid + ":" + authToken);
var phoneDE = DataExtension.Init("[Data Extension external key]");
var numbers = phoneDE.Rows.Retrieve();
var end = numbers.length;
for (var i=0; i<end; i++) {
var config = {
endpoint: "https://api.twilio.com/2010-04-01/Accounts/[accountSid]/Messages.json",
contentType: "application/x-www-form-urlencoded",
payload : "From=[phone]&To=" + numbers[i]["Phone"] + "&Body=Your cöntract is expiring today, you can sign it here: " + numbers[i]["URL"]
};
Write("Payload" + i + ": " + config.payload + " ");
try {
var httpResult = HTTP.Post(
config.endpoint,
config.contentType,
config.payload,
["Authorization"],
["Basic " + auth]
);
var result = Platform.Function.ParseJSON(httpResult.response);
Write(httpResult.StatusCode);
Write("result" + result);
} catch(error) {
Write("Error: " + Stringify(error));
}
}
</script>`
What do I need to do to ensure that my SMS includes the accent characters and that they are not omitted?
Thank you very much for your help.
Thanks for your answer Swimburger. I didn't get a chance to try it as I found another solution. However I do appreciate your feedback, your solution was the next approach I was going to try.
My solution was to modify the contentType of the POST request to include UTF-8 as the character set:
contentType: "application/x-www-form-urlencoded;charset=UTF-8"
Unfortunately, I don't have access to a Salesforce environment to try out your code, but here's a modified version of your code using node.js.
var accountSid = process.env.TWILIO_ACCOUNT_SID;
var authToken = process.env.TWILIO_AUTH_TOKEN;
var auth = Buffer.from(`${accountSid}:${authToken}`).toString('base64');
var body = new URLSearchParams();
body.append("From", "+12345678901");
body.append("To", "+12345678901");
body.append("Body", "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿĀāĂ㥹");
const request = new Request(
`https://api.twilio.com/2010-04-01/Accounts/${accountSid}/Messages.json`,
{
method: 'POST',
body: body.toString(),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': `Basic ${auth}`
}
}
);
fetch(request)
.then(response => response.json())
.then(jsonBody => console.log(jsonBody))
.catch((error) => {
console.error(error);
});
You need to configure the Twilio Account SID and Auth Token as env variables.
After that, running this script sends an SMS and the SMS contains all the characters.
I'm not sure if you are able to use these node.js APIs, but if you don't, this proves that the issue is caused by Salesforce's Server Side JavaScript APIs.
HTTP.Post probably removes the ö character.
If you do have access to node.js/npm packages, you could also use the Twilio helper library for Node.js.
I have IOS app based on phonegap, I want to redirect it to responsive website and set cookies to still logged in with his credentials.
windows.location is not work
Thanks
use "window.location.href"
window.location.href = "your website url here"
it will solve the problem on iOS
I found the solution
function scripting() {
ref.executeScript({
code: 'document.cookie = "token=' + res.data.token + '"; window.location= "' + res.redirectUrl + '"; '
}, function () {
ref.removeEventListener('loadstart', scripting);
});
}
var ref = cordova.InAppBrowser.open(res.redirectUrl, '_blank', 'location=no,toolbar=no');
ref.addEventListener('loadstart', scripting);
I hope it helps who had the same problem
I am currently trying to login to my app that is built on Ionic Framework using Venmo's Oauth API. I am attempting to use the Server Side Flow so that I can have a longer term access token. I am able to receive a code and set it to a requestToken variable.
However, when I attempt to post to "https://api.venmo.com/v1/oauth/access_token" with my Client Id, Client Secret, and Request Token, I get the following error alert: "ERROR: [object Object]".
In checking my console, I see that the error is a 400 Bad Request error coming on my post request, although it does appear that I have a valid request token. The error message is as follows: "Failed to load resource: the server responded with a status of 400 (Bad Request)".
Below is the code of the login function I am using to login via Venmo's Oauth API:
//VENMO SERVER SIDE API FUNCTION
var requestToken = "";
var accessToken = "";
var clientId = "CLIENT_ID_HERE";
var clientSecret = "CLIENT_SECRET_HERE";
$scope.login = function() {
var ref = window.open('https://api.venmo.com/v1/oauth/authorize?client_id=' + clientId + '&scope=make_payments%20access_profile%20access_friends&response_type=code');
ref.addEventListener('loadstart', function(event) {
if ((event.url).startsWith("http://localhost/callback")) {
requestToken = (event.url).split("?code=")[1];
console.log("Request Token = " + requestToken);
$http({
method: "post",
url: "https://api.venmo.com/v1/oauth/access_token",
data: "client_id=" + clientId + "&client_secret=" + clientSecret + "&code=" + requestToken
})
.success(function(data) {
accessToken = data.access_token;
$location.path("/make-bet");
})
.error(function(data, status) {
alert("ERROR: " + data);
});
ref.close();
}
});
}
if (typeof String.prototype.startsWith != 'function') {
String.prototype.startsWith = function(str) {
return this.indexOf(str) == 0;
};
}
This function is from this helpful walkthrough article by Nic Raboy (https://blog.nraboy.com/2014/07/using-oauth-2-0-service-ionicframework/). I think that the problem may be in how I am presenting the data array, so if anyone has any experience in successfully implementing a Venmo API in Ionic, your help would be much appreciated!
I was actually able to solve this issue with the method described above. In my original code, I omitted the line used to set the content type to URL encoded (which was included in Nic's example). Once I added this line, the request functioned as expected. The line was as follows:
$http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
i am having a strange problem.
I use OAuth2 and gapi.auth.authorize({client_id:'...',scope:'../youtube',immediate:false}) to log a user into my app. This method lets the user choose which of his connected accounts(identities) to use.
I retrieve user's video using gapi.client.youtube.channels.list and gapi.client.youtube.playlistItems.list.
later in the same app the user can click a button to choose another of his connected accounts(identities). i use again gapi.auth.authorize({client_id:'...',scope:'../youtube',immediate:false}) method.
the problem is that after successfull change of the account the gapi.client.youtube.channels.list method returns the cached result from the first call.
some remarks:
-in ie 11 it works fine
- in google chrome, if i disable the cache from developers tools it also works fine
- before the call to channels.list i call /oauth2/v2/tokeninfo and /plus/v1/people/me and they both return correct results, that is the second account's data
is there any way to correct this?
thank you.
Someone can overcome this by using XMLHttpRequest( see https://developers.google.com/api-client-library/javascript/features/cors) . It's probably a bug of javascript YouTube api.
What worked for me is to introduce a silly extra parameter on the request to cheat Google's system... Or at least that's my impression, because it seems to work consistently:
I just add it to the URL:
"https://www.googleapis.com/youtube/v3/channels?mine=true" +
"&part=" + encodeURIComponent("id,snippet") +
"&key=" + encodeURIComponent(API_KEY) +
"&random=" + encodeURIComponent(Math.random().toString())
Here's the full example:
refreshChannels(): Promise<YoutubeChannel[]> {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
this.channels = JSON.parse(xhr.response).items.map(ch => new YoutubeChannel().deserialize(ch));
console.log("[Youtube][loadChannels] Got some channels:");
console.log(this.channels);
this.onReceivedYoutubeChannels.next(this.channels);
resolve(this.channels);
} else {
reject(JSON.parse(xhr.response));
}
}
};
xhr.onerror = () => reject();
const user = gapi.auth2.getAuthInstance().currentUser.get();
const oAuthToken = user.getAuthResponse().access_token;
xhr.open(
"GET",
"https://www.googleapis.com/youtube/v3/channels?mine=true&part=" +
encodeURIComponent("id,snippet") +
"&key=" +
encodeURIComponent(API_KEY) +
"&random=" + encodeURIComponent(Math.random().toString())
);
xhr.setRequestHeader("Authorization", "Bearer " + oAuthToken);
xhr.send();
});
}
I get different ETags. I saw as well a Cache-Control response header that might be caching too?
cache-control: private, max-age=300, must-revalidate, no-transform
With my solution I can overcome it. If someone understands why it would be great if could elaborate more on this solution.
Is there any way to send Ajax requests to server from a Firefox plugin? If yes, how? If no, how do we have client server communication in Firefox plugins?
I want to get some JSON data from server and manipulate the DOM object according to the client input.
I am pretty a beginner in plugin programming.
You can send ajax requests from firefox extension using xmlHTTPRequest, like in any other web application.
From a contentscript you should add the permissions to access cross-domain content, URLs you want to:
"permissions": {
"cross-domain-content": ["http://example.org/", "http://example.com/"]
}
More info in the documentation.
Here's a simple snippet that does XHR request, WITHOUT cookies (due to flag Ci.nsIRequest.LOAD_ANONYMOUS can remove to send with cookies) (MDN :: Info on flags]. Copy this first code block in, then see usage examples below.
var {Cu: utils, Cc: classes, Ci: instances} = Components;
Cu.import('resource://gre/modules/Services.jsm');
function xhrGetPost(url, post_data, cb) {
let xhr = Cc["#mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
let handler = ev => {
evf(m => xhr.removeEventListener(m, handler, !1));
switch (ev.type) {
case 'load':
if (xhr.status == 200) {
cb(xhr.response);
break;
}
default:
Services.prompt.alert(null, 'XHR Error', 'Error Fetching Package: ' + xhr.statusText + ' [' + ev.type + ':' + xhr.status + ']');
break;
}
};
let evf = f => ['load', 'error', 'abort'].forEach(f);
evf(m => xhr.addEventListener(m, handler, false));
xhr.mozBackgroundRequest = true;
if (post_data == undefined) {
post_data = null;
}
if (post_data) {
xhr.open('POST', url, true);
} else {
xhr.open('GET', url, true);
}
xhr.channel.loadFlags |= Ci.nsIRequest.LOAD_ANONYMOUS | Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsIRequest.INHIBIT_PERSISTENT_CACHING;
//xhr.responseType = "arraybuffer"; //dont set it, so it returns string, you dont want arraybuffer. you only want this if your url is to a zip file or some file you want to download and make a nsIArrayBufferInputStream out of it or something
xhr.send(post_data);
}
Example usage of for POST:
var href = 'http://www.bing.com/'
xhrGetPost(href, 'post_data1=blah&post_data2=blah_blah', data => {
Services.prompt.alert(null, 'XHR Success', data);
});
Example usage of for GET:
var href = 'http://www.bing.com/'
xhrGetPost(href, null, data => {
Services.prompt.alert(null, 'XHR Success', data);
});