Error when made AngularJS $http request POST - javascript

I want to access POST method from my server, but when I logged the response, it's always return status=0, anyone can help me or give me an advise?
note: I've tried my method in Postman and it's works anyway
This is my contorller
nameApp.controller('loginCtrl', ['$scope','$location','Flash','$sessionStorage', '$cookieStore','$http',function (scope,location,Flash,sessionStorage,cookieStore,http) {
scope.nim='';
scope.pass='';
if(cookieStore.get('current')!=null){
location.path('/homepage')
}
scope.login = function() {
if((scope.nim=='')){
Flash.create('danger', 'Invalid Username / Password', 'custom-class');
}else{
http.post('http://localhost:8084/iec3/rest/users/login',{'username':'admin','password':'bukanadmin'},{headers: {'Content-Type': 'application/json'}
}).then(function successCallback(response) {
console.log("GREAT");
}, function errorCallback(response) {
console.log(response)
});
}
}
}]);
This is login method from my controller
#Path("/login")
#POST
#Consumes(value = MediaType.APPLICATION_JSON)
#Produces(value = MediaType.APPLICATION_JSON)
public Response login(User user) {
UserDao ud = new UserDao();
User dariDB = ud.login(user.getUsername(), user.getPassword());
dariDB.setPassword("");
return Response.ok(dariDB)
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Headers", "origin, content-type, accept, authorization")
.header("Access-Control-Allow-Credentials", "true")
.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD")
.header("Access-Control-Max-Age", "1209600")
.build();
}
This Is the error when i try to logged the response
Object {data:null, status:0, headers:dd/<(), config:Object, statusText:""}

You need to verify if your request is reaching to the server. Is your login method is getting called? If you are on same host, there is no need to pass complete url, you can directly call your api via its path.
As for a newbie, I would recommend you to avoid $http shortcut methods. For better understanding and readability, you should use $http like
$http({
method: 'POST',
url: 'http://localhost:8084/iec3/rest/users/login',
data: {
username:'admin',
password:'bukanadmin'
},
headers: {
'Content-Type': 'application/json'
}
}).then(function successCallback(response) {
console.log("GREAT");
}, function errorCallback(response) {
console.log(response)
});

Your request from ajax does not seem to hit your controller method, status 0 is usually returned when the request is cancelled. Check the #path value in controller method and the http://localhost:8084/iec3/rest/users/login mapping.
For more details about status 0
http://www.w3.org/TR/XMLHttpRequest/#the-status-attribute

Related

400 Bad Request error when sending POST request to WCF service using JavaScript

I have a very simple self-hosted WCF application initialized this way:
Host = new WebServiceHost(this, new Uri(serviceAddress));
var binding = new WebHttpBinding();
binding.ReceiveTimeout = TimeSpan.MaxValue;
binding.MaxReceivedMessageSize = int.MaxValue;
binding.CrossDomainScriptAccessEnabled = true; // TODO: Remove this?
var endpoint = Host.AddServiceEndpoint(typeof(HttpService), binding, "");
Host.Open();
My HttpService class has this method:
[OperationContract, WebInvoke(Method = "*")]
public string Evaluate(string query)
{
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*");
if (WebOperationContext.Current.IncomingRequest.Method == "OPTIONS")
{
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Methods", "POST, PUT, DELETE");
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With");
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Max-Age", "1728000");
return "";
}
else
{
try
{
return "12345";
}
catch (ProcessNotFoundException ex)
{
throw new WebFaultException<string>(ex.Message, System.Net.HttpStatusCode.NotFound);
}
catch (Exception ex)
{
throw new WebFaultException<string>(ex.Message, System.Net.HttpStatusCode.InternalServerError);
}
}
}
I added the CORS stuff above so that anyone can use this API from any website using JavaScript. And I'm trying to run some POST requests using fetch because once it works, I'll pass large amounts of data so a GET method won't work. Doing the following from JavaScript works OK:
fetch('http://localhost:8001/HeliumScraperService/Evaluate', { method: 'POST', headers: { "Content-Type": 'application/json' }, body: '1232'});
When I do that, my Evaluate method is called first with OPTIONS and then with POST, and an XML string is returned with no errors. The following also works (note the quotes inside the body):
fetch('http://localhost:8001/HeliumScraperService/Evaluate', { method: 'POST', headers: { "Content-Type": 'application/json' }, body: '"hello world"'});
Since both are valid JSON, I though any JSON string would work, so I did this but I got a 400 Bad Request error:
fetch('http://localhost:8001/HeliumScraperService/Evaluate', { method: 'POST', headers: { "Content-Type": 'application/json' }, body: '[10]'});
I thought maybe it wants a JSON that it can convert to my method arguments, but this also doesn't work (gives me a 400 error):
fetch('http://localhost:8001/HeliumScraperService/Evaluate', { method: 'POST', headers: { "Content-Type": 'application/json' }, body: JSON.stringify({ query: "hey" })})
So it can take numbers and strings but nothing else, and I have no idea why. I tried using all these other attribute combinations and got the exact same results:
[OperationContract, WebInvoke(Method = "*", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json)]
[OperationContract, WebInvoke(Method = "*", BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json)]
[OperationContract, WebInvoke(Method = "*", BodyStyle = WebMessageBodyStyle.Bare)]
[OperationContract, WebInvoke(Method = "*", BodyStyle = WebMessageBodyStyle.Wrapped)]
I just want to be able to send any string, without something looking into it and deciding whether it's good or bad, while also being able to do the CORS thing above. Is there a way to do this?
I found a workaround but I'm still not sure why it was letting me pass numbers and strings but not arrays, so if someone comes up with an actual explanation I'll be happy to accept that as an answer. My solution was to take a Stream instead of a string in my Evaluate method, and then read the stream like:
using (var memoryStream = new MemoryStream())
{
query.CopyTo(memoryStream);
var array = memoryStream.ToArray();
var lole = Encoding.UTF8.GetString(array);
}
I think the idea is that, since I'm doing the CORS thing and the browser sends an empty body when sending an OPTIONS request, WCF can't handle that as JSON so I have to handle everything myself and the way to do that is by taking a war Stream. Still no idea why it was letting me send numbers and strings (and booleans too BTW) but no arrays (or objects).
At first, the following definition only supports to accept the parameters by using request body, instead of the URL Params.
[OperationContract, WebInvoke(Method = "*")]
public string Evaluate(string query)
Moreover, the body style of the parameters is bare by default.
BodyStyle =WebMessageBodyStyle.Bare
It means that the server accepts the string without wrapping the name of the parameter.
body: '1232'
body: '"hello world"'
When we manually switch the value to BodyStyle=WebMessageBodyStyle.Wrapped, the server will accept the below form. Basically, your attempts are correct. There is just a small problem here.
{"value":"abcd"}
Here is my example, wish it is helpful to you.
Server contract.
[OperationContract]
[WebInvoke(Method ="*",BodyStyle =WebMessageBodyStyle.Wrapped,ResponseFormat =WebMessageFormat.Json)]
string GetData(string value);
JS
<script>
var para1 = { "value": "abcdefg" };
$.ajax({
type: "POST",
url: "http://localhost:8864/Service1.svc/getdata",
data: JSON.stringify(para1),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: OnSuccessCall,
error: OnErrorCall
});
function OnSuccessCall(response) {
console.log(response);
}
function OnErrorCall(response) {
console.log(response.status + " " + response.statusText);
}
</script>
About handing the CORS issue, I add an extra global.asax file.
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Cache-Control, Pragma, Origin, Authorization, Content-Type, X-Requested-With,Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}
Here is a related document.
https://learn.microsoft.com/en-us/dotnet/api/system.servicemodel.web.webmessagebodystyle?view=netframework-4.8
Feel free to let me know if there is anything I can help with.

Error -1 send parameters using $http.post angular

I have a problem when you submit parameters using $ http.post in angular.
I assume it's some sort of error itself have little knowledge of angular , because in jquery work fine.
Request jquery'javascript
var user = $('#usuariotxt').val();
var pass = $('#passwordtxt').val();
var login= {
Usuario : user,
Password : pass
};
$.ajax({
type: 'POST',
url: 'http://190.109.185.138/Apipedro/api/login',
data: login,
datatype: 'json'
}).done(function(data) {
console.log(data);
});
Request Angular-Javascript
var app;
app = angular.module('AppUPC',[]);
app.controller('Formulario',['$scope', '$http', function ($scope, $http){
$scope.login = function(){
var login = {
Usuario: $scope.usuariotxt,
Password: $scope.passwordtxt
};
console.log(login);
var url, method;
url = 'http://190.109.185.138/Apipedro/api/login';
method = 'POST';
$http.post("http://190.109.185.138/Apipedro/api/login", {},
{params: {Usuario:$scope.usuariotxt, Password:$scope.passwordtxt}
}).success(function (data, status, headers, config) {
$scope.persons = data;
console.log($scope.persons);
}).error(function (data, status, headers, config) {
$scope.status = status;
console.log($scope.status);
});
};
}]);
I have also used many other forms , including the most common
$http({
url: url,
method: method,
data: login,
headers :{'Content-Type':'application/json'}
})
Errors that occur to me are the following
Short answer: If you want to send the same data as the jQuery example, use this
app.controller('Formulario', ['$scope', '$http', '$httpParamSerializer', function ($scope, $http, $httpParamSerializer) {
// snip
$http.post(url, $httpParamSerializer(login), {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(function success(response) {
$scope.persons = response.data;
}, function error(response) {
$scope.status = response.status;
});
}]);
This is because jQuery by default sends POST data as an x-www-form-urlencoded string, ie
Usuario=dfvides&Password=dfvids
Using the code above, Angular will send an identical request to jQuery.
Angular by default sends POST data as JSON with the Content-Type header set to application/json, ie
{"Usuario":"dfvides","Password":"dfvids"}
Is your API even set up to handle a JSON payload?
The reason your Angular version was triggering a pre-flight OPTIONS request (which it appears that your API is not equipped to handle) was because the header Content-Type: application/json makes the request non-simple...
A simple cross-site request is one that:
Only uses GET, HEAD or POST. If POST is used to send data to the server, the Content-Type of the data sent to the server with the HTTP POST request is one of application/x-www-form-urlencoded, multipart/form-data, or text/plain.
Does not set custom headers with the HTTP Request (such as X-Modified, etc.)

Angular $http service / controller to JSONP

Due to my cross domain errors, I am trying to convert my $http call to a JSONP one.
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:5000' is therefore not allowed
access.
I'm a beginner and having extracted my GET service from my controller, I'm struggling with finding the spot where to change $http to $http.jsonp(url) based on the Angular documentation
Here's my service.js:
.service('NCAAF',function($http, $ionicLoading) {
return {
get: function() {
$ionicLoading.show({
template: 'Loading...',
delay: 300
})
return $http (
{
method: 'GET',
cache: true,
crossDomain: true,
dataType: 'jsonp',
url: 'https://www.kimonolabs.com/api/[key]?callback=JSON_CALLBACK',
headers: {
'authorization': 'Bearer [auth]'
}
});
}
};
})
and controller.js:
.controller('NCAAFCtrl', function ($scope, NCAAF, $ionicPopup, $ionicLoading) {
var doGet = function() {
NCAAF.get().
success(function (data) {
$scope.data = data['results']['collection1'];
$ionicLoading.hide();
}).
error(function () {
$ionicLoading.hide();
var alertPopup = $ionicPopup.alert({
title: 'Something went wrong',
template: 'Try reloading in a few seconds.'
});
alertPopup.then(function() {
console.log('Fix this ish');
});
}).
finally(function() {
$scope.$broadcast('scroll.refreshComplete');
});
};
$scope.doRefresh = function() {
doGet();
};
doGet();
})
JSONP can make you do cors request ,but that doesn't mean you will be able to get correct response.
JSONP requires you to wrap your JSON response into a Javascript function call.
When you do a JSONP the request , query string will set a parameter called
'callback' that will tell your server how to wrap the JSON response.
The server should use the callback parameter from the request string to set the
response accordingly.
So the response should be
callback([ {“access_token”: “asdfsd”, “expires”: “86400" ,"type" : "bearer"}
]);
In angular it will look like
angular.callbacks._0([ {“access_token”: “asdfsd”, “expires”: “86400" ,“type” :
“bearer”} ]);
But just for your information about how to make jsonp call ,change your code
return $http (
{
method: 'GET',
cache: true,
crossDomain: true,
dataType: 'jsonp',
url: 'https://www.kimonolabs.com/api/[key]?callback=JSON_CALLBACK',
headers: {
'authorization': 'Bearer [auth]'
}
});
to
return $http.jsonp('https://www.kimonolabs.com/api/[key]?callback=JSON_CALLBACK',{
headers: {
'authorization': 'Bearer [auth]'
}
});

Angular - How to work with HTTPS using $http

just wanted to ask on how to deal with https + cross-domain url using $http?
I've used $.ajax to solve my problem, but the reason why I wanted to use $http more is because I have an $http interceptor since using $.ajax takes a lot more line of codes rather than having an interceptor to automate some process.
I've read similar posts [link1, link2, link3] but neither of them have solved my problem.
I have an attached screenshot of my console, I hope it makes sense:
.
The weird thing is the OPTION Method being used by $http which I have set it to POST
Here's my code snapshot:
$http({
method: 'POST',
url: '/HearingCentre',
data: {
Type: ['P', 'V']
},
success: function (res) {
console.log(res);
d.resolve(res);
},
error: function (res) {
console.log(res);
d.reject(res);
}
});
NOTE: I'm using an $http interceptor here so basically the URL will be appended with the base API URL
$.ajax version
$.ajax({
method: 'POST',
crossDomain: true,
url: 'https://ahtstest.hearing.com.au/services/api/HearingCentre',
data: {
Type: ['P', 'V']
},
success: function (res) {
console.log(res);
},
error: function (res) {
console.log(res);
}
});
Do anyone have a solution for this?
var userApp = angular.module('userApp', []);
userApp.controller('UserController', function ($scope,$http) {
//server call with angular
$scope.makeServerCall = function() {
var url = '/root/jsp/catalog/xml/getJsp.jsp?PatientId=9175;
$http({
crossDomain: true,
xhrFields: {withCredentials: false},
headers: {'Accept': 'application/json','Content-Type': 'application/json'},
method: 'GET',
url: url
}).then(function(response) {
console.log("Success: "+JSON.stringify(response));
},function(response) {
console.log("Error: "+JSON.stringify(response));
});
};
}
And make sure that at your server side you can accessible to cross domain reuqest. Lets say I am using Spring MVC so I have added one filter and configure cross domain request to allow as follow. If you using any other language lets say PHP, then you have to set response header.you can search for the same.
My Server filter Spring mvc
#Component
public class EcwCORSFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With,isAjaxRequest");
chain.doFilter(req, res);
}
public void init(FilterConfig filterConfig) {
}
public void destroy() {
}
}

API invoked failed: Custom headers present ; using Angular $http.get

(function(){
app = angular.module('mySupport',['ngRoute']).controller('knwCenterCtrl');
var config = {
headers : {
'Accept': 'application/vnd.*********+json',
'Accept-Encoding': 'gzip,deflate',
'custom-header': '12345',
'Access-Control-Request-Headers': 'Accept, custom-header'
},
responseType: 'json'
};
app.controller('knwCenterCtrl', function($scope, $http) {
$http.get("https://abcdefg.com/support/pub/navigation/products", config)
.success(function(response)
{
$scope.prodFam = response.productFamily;
// console.log($scope.mycases);
});
});
})();
What am I missing in this get request? I was able to successfully invoke another APi from the same server using the same code. But for some reason, the code is not making any call to the server. Why is that? Please help.
Thanks,

Categories

Resources