AJAX request failing in jQuery but not in NodeJS - javascript

I have a RESTful web service (hosted on a different server via IIS) that returns JSON. The strange thing is the following NodeJS command line test application (not via the web browser, but via the command line) is working fine and returning the JSON:
Working NodeJS App:
var request = require("request");
var btoa = require("btoa");
var uname = "corp\\user.name";
var pword = "password123"
var options = {
url: "http://192.168.3.142/v1/foo?format=json",
headers: {
"Authorization": "Basic " + btoa(uname + ":" + pword)
}
};
request(options, function(err, response, body) {
console.log(body);
});
However the following AJAX request fails with:
OPTIONS http://192.168.3.142/v1/foo?format=json 401 (Unauthorized) jquery-1.11.0.min.js:4
XMLHttpRequest cannot load http://192.168.3.142/v1/foo?format=json. Invalid HTTP status code 401
This is the response header from the server:
Response Headers:
Access-Control-Allow-Headers:Authorization
Access-Control-Allow-Methods:GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin:*
Content-Length:1293
Content-Type:text/html
Date:Thu, 06 Mar 2014 05:41:24 GMT
Server:Microsoft-IIS/7.5
WWW-Authenticate:Basic realm="192.168.3.142"
X-Powered-By:ASP.NET
AJAX code:
$.ajaxSetup({
beforeSend: function (xhr, settings) {
var creds = {
username: "corp\\user.name",
password: "password123"
};
xhr.setRequestHeader("Authorization", "Basic " + btoa(creds.username + ":" + creds.password));
return true;
}
});
$.ajax({
type: "GET",
url: "http://192.168.3.142/v1/foo?format=json",
success: function (data, text) {
console.log(data);
}
});
UPDATE:
Throws the same 401 (Unauthorized):
var creds = {
username: "corp\\user.name",
password: "password123"
};
var credentials = btoa(creds.username + ":" + creds.password);
$.ajax({
type: "GET",
dataType: "text/json",
url: "http://192.168.3.142/v1/foo?format=json",
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", "Basic " + credentials);
return true;
},
success: function (data, text) {
console.log(data);
}
});

Once I added xhrFields: { withCredentials: true } to the $.ajaxSetup({}); the error was returning:
Credentials flag is 'true', but the 'Access-Control-Allow-Credentials' header is ''. It must be 'true' to allow credentials.
I added Access-Control-Allow-Credentials: true on the server-side and it's now working correctly.
var creds = {
username: "username",
password: "password"
};
var credentials = btoa(creds.username + ":" + creds.password);
$.ajaxSetup({
xhrFields: { withCredentials: true },
beforeSend: function (xhr, settings) {
xhr.setRequestHeader("Authorization", "Basic " + credentials);
return true;
}
});
$.ajax({
type: "GET",
url: "http://localhost/v1/service",
async: true,
success: function (data, text) {
console.log(data);
}
});

Related

jQuery REST PUT request doesn't work in my code?

I just want to make a PUT request with jQuery in Jira.
I've tried it before with SoapUI and there it works, but in my JS file it's not working... It's always giving me an error back (alert with "no" in my case).
Here's my code:
var issueKey = this.JIRA.Issue.getIssueKey();
var username = "admin";
var password = "admin";
var encodedLoginData = btoa(username + ":" + password);
AJS.$.ajax({
type: 'PUT',
contentType: 'application/json',
url: '/jira/rest/api/2/issue/' + issueKey,
dataType: 'json',
async: false,
headers: { 'Authorization': 'Basic ' + encodedLoginData },
data: JSON.stringify('{"update":{"timetracking":[{"edit":{"originalEstimate":"4m","remainingEstimate":"3m"}}]}}'),
success: function(response){ alert("yes"); },
error: function(error){ alert("no"); }
});
As mentioned, the JSON data phrase works in SoapUI, also the login information and the base64 encryption. That's all correct.
But I can't find my fault... Any ideas?
EDIT:
PUT http://localhost:2990/jira/rest/api/2/issue/TEST-3 400
XMLHttpRequest.send # batch.js?devtoolbar=…logged-in=true:5461
send # batch.js?locale=en-US:197
ajax # batch.js?locale=en-US:191
calculate # batch.js?devtoolbar=…logged-in=true:5620
prepareCalculation # batch.js?devtoolbar=…logged-in=true:5620
(anonymous) # batch.js?devtoolbar=…logged-in=true:5620
dispatch # batch.js?locale=en-US:104
h # batch.js?locale=en-US:96
trigger # batch.js?locale=en-US:101
simulate # batch.js?locale=en-US:108
e # batch.js?locale=en-US:114
I think your problem is that the parameter of your JSON.stringify shouldn't be a String. Try to save that into a variable and then make a JSON.stringify of that.
Take into account the result of JSON.stringify. For instance:
JSON.stringify("{}"); //""{}""
JSON.stringify({}); //"{}"
Now your code should be like this For example:
var issueKey = this.JIRA.Issue.getIssueKey();
var username = "admin";
var password = "admin";
var encodedLoginData = btoa(username + ":" + password);
var dataObject = {"update":{"timetracking":[{"edit":{"originalEstimate":"4m","remainingEstimate":"3m"}}]}};
AJS.$.ajax({
type: 'PUT',
contentType: 'application/json',
url: '/jira/rest/api/2/issue/' + issueKey,
dataType: 'json',
async: false,
headers: { 'Authorization': 'Basic ' + encodedLoginData },
data: JSON.stringify(dataObject),
success: function(response){ alert("yes"); },
error: function(error){ alert("no"); }
});
If this is an IIS server, you may need to disable WebDAV, as that grabs all PUT requests.
Happens to be your error is that you're trying to stringify a string
data: JSON.stringify('{update...}')
Nowadays, you don't need jQuery to do HTTP in the browser. All modern browsers come with the Fetch API built in
const issueKey = this.JIRA.Issue.getIssueKey();
const username = "admin";
const password = "admin";
const encodedLoginData = btoa(username + ":" + password);
const body = {
update: {
timetracking: [{
edit: {
originalEstimate: "4m"
remainingEstimate: "3m"
}
}]
}
}
fetch(`/jira/rest/api/2/issue/${issueKey}`, {
method: 'PUT',
body: JSON.stringify(body),
headers: {
'Authorization': 'Basic ' + encodedLoginData
'Content-Type': 'application/json',
},
})
.then(response => alert('yes'))
.catch(error => alert('no'));

How to call Web API from ExtJS with token based authentication

Ext.Ajax.request({
url: 'Employee/Search',
method: 'POST',
headers: { "Content-Type":"application/json","Accept": "application/json","Authorization": "OAuth oauth_token=158ghhBtgf2586525hggfgdf" },
jsonData: {
"FirstName": txtFirstName.getValue()
},
success: function(response) {
},
failure: function(response) {
}
});
This is giving me 401 (Unauthorized Request)
I am using adal.js library by Microsoft, and using the following code:
window.acquireTokenCallback = function (error, token) {
if(error || !token) {
Ext.alert('ADALERROR', error || 'Token empty');
return;
}
// Apply token to all future Ajax requests.
Ext.Ajax.setDefaultHeaders({
'Authorization': 'Bearer ' + token,
'Accept': 'application/json'
});
// Load Settings from Server.
me.loadSettings();
};

AngularJS service to send Twilio SMS messages

I've been experimenting with creating an AngularJS service that can be called from the controller and send text messages based on particular events in the application. The implementation is based on this, and works as follows:
Firstly, we have the service:
function BusinessService($http) {
this.twilioSMS = {
sendMessage: function(to, from, body) {
var accountSid = 'xxx';
var authToken = 'xxx';
var testEndpoint = 'https://api.twilio.com/2010-04-01/Accounts/' + accountSid + '/SMS/Messages.json';
var liveEndpoint = 'https://api.twilio.com/2010-04-01/Accounts/' + accountSid + '/Messages.json';
var data = {
To: to,
From: from,
Body: body
};
$http({
method: 'POST',
url: testEndpoint,
data: data,
dataType: 'json',
contentType: 'application/x-www-form-urlencoded',
beforeSend: function(xhr) {
xhr.setRequestHeader("Authorization",
"Basic " + btoa(accountSid + ":" + authToken) // !
);
},
success: function(data) {
console.log("Got response: %o", data);
if (typeof successCallback == 'function')
successCallback(data);
},
error: function(jqXHR, textStatus, errorThrown) {
console.log("Request failed: " + textStatus + ", " + errorThrown);
if (typeof failCallback == 'function')
failCallback(jqXHR, textStatus, errorThrown);
}
})
}
}
}
Then setting it up in the controller:
function ConsumerBusinessProfileCtrl($scope, BusinessService) {
$scope.sendMessage = function(to, from, body) {
return BusinessService.twilioSMS.sendMessage(to, from, body)
}
}
And then calling it from the view:
<a ng-click="sendMessage('+12345678901', '+15005550006', 'Hey Jenny! Good luck on the bar exam!')">Send Message</a>
I've tested the jsfiddle example with my accountSid, authToken, and phone numbers and it is working fine. But my implementation fails with a 401 (UNAUTHORIZED) error. A part of me thinks that this is because $http does not support beforeSend or afterSend. But I am not sure? Can anybody here guide me in the right direction?
Changed $http to the following to fix things:
$http({
method: 'POST',
url: testEndpoint,
data: data,
transformRequest: function(obj) {
var str = [];
for (var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
},
headers: {
'Authorization': 'Basic ' + btoa(accountSid + ':' + authToken),
'Content-Type': 'application/x-www-form-urlencoded'
},
}).success(function(response) {
console.log(response);
}).error(function(error) {
console.log(error);
});
}

AJAX POST in .NET

I have the below javascript AJAX request which works:
$.ajax({
type: "POST",
url: requestUrl,
data: {
var1: 'value1',
var2: 'value2',
var3: 'value3'
},
xhrFields: {
withCredentials: true
},
dataType: "json",
crossDomain: true,
complete: function (jqXhr, textStatus) {
if (jqXhr !== undefined && jqXhr !== null && jqXhr.statusText === "OK") {
alert("Request Success" + jqXhr.responseText);
} else {
alert("Request Failed" + (jqXhr.responseText || textStatus));
}
}
});
I would like to do the same using .NET.
I tried the following:
string result = string.Empty;
try
{
using (var client = new WebClient())
{
client.Credentials = new NetworkCredential("userName", "password");
var values = new NameValueCollection();
values["var1"] = "value1";
values["var2"] = "value2";
values["var3"] = "value3";
var response = client.UploadValues(requestUrl, values);
result = Encoding.Default.GetString(response);
}
}
catch (Exception exception)
{
Console.WriteLine("Error=" + exception.Message);
}
Console.WriteLine("result=" + result);
However I get an Internal Server Error.
How do I recreate a cross domain request? Is there a specific header to set?
WebException details:
Response: "The remote server returned an error: (500) Internal Server Error."
Headers:
Persistent-Auth: true
Content-Length: 5143
Cache-Control: private
Content-Type: text/html; charset=utf-8
Date: Tue, 14 Jul 2015 12:03:21 GMT
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Without seeing the error it's hard to say exactly what's going on but if you suspect this is a CORS issue then you can add these headers:
var data = JsonConvert.SerializeObject(
new
{
Prop1 = 1,
Prop2 = "data 2"
});
using (var client = new WebClient { UseDefaultCredentials = true })
{
client.Headers.Add("access-control-allow-origin", "*");
client.Headers.Add("access-control-allow-methods", "GET, POST, OPTIONS");
client.Headers.Add("access-control-allow-headers", "Authorization, content-type, accept");
client.Headers.Add(HttpRequestHeader.ContentType, "application/json; charset=utf-8");
client.UploadData("your url", "POST", Encoding.UTF8.GetBytes(data));
}

run ajax without authorization headers

I want to create ajax call with authorization headears only when user writes username and password. When this vars are empty I need to create ajax call without authorization headers. How can I do this? Can I make it with one ajax or I need to create two ajax every for one situation?
var username = "user123";
var password = "pass123";
//var username = "";
//var password = "";
$.ajax({
type: "GET",
url: url_survey,
dataType: "json",
headers: {
'Authorization': "Basic " + btoa(username + ":" + password)
},
success:
function (data) {
alert("SUCCESS");
},
error:
function (data) {
alert("ERROR");
}
});
Try this:
var username = "user123";
var password = "pass123";
//var username = "";
//var password = "";
var headers = {}; //list of headers
if(username && password) //user and pass exists
headers['Authorization'] = "Basic " + btoa(username + ":" + password);
$.ajax({
type: "GET",
url: url_survey,
dataType: "json",
headers: headers, //use our headers
success:
function (data) {
alert("SUCCESS");
},
error:
function (data) {
alert("ERROR");
}
});
The parameter passed to $.ajax is just an object. Just simply create it, add properties as needed, then send it to `$.ajax.
var ajaxData = {
type: "GET",
url: url_survey,
dataType: "json",
success:
function (data) {
alert("SUCCESS");
},
error:
function (data) {
alert("ERROR");
}
};
if(username && password){
ajaxData.headers = {
'Authorization': "Basic " + btoa(username + ":" + password)
};
}
$.ajax(ajaxData);

Categories