Getting 304 status code through a web api call only using IE11 - angularjs

I am getting 304 status code through a angular JS webApi get request only using IE11. When I press Ctrl+F5, it corrects and get 200 status code (which is correct behavior). It works fine using Chrome. I am using following code.
factory('StudentService', function ($q, $http, pathProvider, searchParams, student) {
return {
getStudents: function (successcb) {
var deferred = $q.defer();
var url = pathProvider.getPath("Student/GetStudents");
$http({
method: 'GET'
, url: url
, cache:false
}).
success(function (data, status, headers, config) {
deferred.resolve(data);
}).
error(function (data, status, headers, config) {
deferred.reject(status);
alert('getStudents ' + status + ': ' + data);
});
return deferred.promise;
}
}
It appears IE has some problem.
Thanks

IE probably adds a If-Modified-Since or If-None-Match request header to the request. If you press CTRL+F5, you force a browser refresh, which means that IE does not add these headers.
It seems that IE does not interpret the angular option cache:false very well. I don't know whether this is an IE or an angular issue, but you can resolve it in javascript by making sure the request is unique. For instance, by adding a dummy parameter to the query string:
$http({
method: 'GET'
, url: url
, cache:false
, params: { 'foobar': new Date().getTime() }
})
You can also fix this on the server by disallowing any browser caching. How you do that depends on the server technology you use.

Related

angular laravel nginx 400 Bad Request

Help, I've got 400 error on POST and or PUT method, but GET works just fine,
I'm using angular as front end and laravel as API, my server is using nginx,
I've used CORS and I everything works fine on my local vagrant which is running on apache.
I'm sure I have my route set correctly, here's some of it from the module I use:
Route::group(array('prefix'=>'/api', 'middleware' => 'cors'),function(){
Route::post('/create_level', 'LevelController#store');
Route::get('/read_level', 'LevelController#index');
Route::get('/read_level/{id}', 'LevelController#show');
Route::put('/read_level/{id}', 'LevelController#update');
Route::delete('/read_level/{id}', 'LevelController#destroy');
here's part of my angular service:
app.service("edulevelService", function ($http, $q, $rootScope)
{
edu.updateEdulevel = function(id, edu){
var deferred = $q.defer();
$http.put($rootScope.endPoint + 'read_level/'+ id, edu)
.success(function(res)
{
deferred.resolve(res);
})
.error(function(err, stat){
deferred.reject(err);
console.log('error code: Ser-UEDU');
});
return deferred.promise;
}
edu.createEdulevel = function(edu){
var deferred = $q.defer();
$http.post($rootScope.endPoint + 'create_level', edu)
.success(function(res)
{
deferred.resolve(res);
})
.error(function(err, stat){
deferred.reject(err);
console.log('error code: Ser-CEDU');
});
return deferred.promise;
}
....
oh I forgot to mention different method cause different error code POST cause 405, PUT cause 400, and I've tried using Postman:
POST is working using text type and return 405 using application/json,
but when I tried
PUT method even though it return 200 I only got NULL data entered to my db (text type), and if I use application/json it return 400
Please Help
Finally found solution:
change $http.post to:
$http({
method: "post",
url: $rootScope.endPoint + 'create_level',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
data: $.param({ .... })
})
somehow it works, exept on my login page which using stellizer to do post method and i can't find how should I change it without breaking all the function...
any one?
I only need to add:
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
and
data: $.param({ ...... })

Angular REST cannot return simple data

I am trying to get a $http REST GET call working in my Appgyver project working but nothing I do seems to come right, always returns an error.
Please note the angular app will be running on mobile devices eventually and then connect to my remote web service.
I've double checked that my custom API is working and returning data correctly in a number of ways, namely:
hard coded cUrl request running from sh files in terminal - Returns data and correct 200 code
Tested the API end points in both POSTMAN and Firefox's SOA client.
Putting in my test end point of http://somesite.com/quote-and-buy-performance/druidapi/taxonomy_term returns data as below:
[{"tid":"1","vid":"2","name":"ACME Ltd.","description":"","format":"filtered_html","weight":"0","parent":"0","uri":"http://somesite.com/quote-and-buy-performance/druidapi/taxonomy_term/1"},{"tid":"2","vid":"2","name":"ABC Films LTD","description":"","format":"filtered_html","weight":"0","parent":"0","uri":"http://somesite.com/quote-and-buy-performance/druidapi/taxonomy_term/2"}]
Even a simple CSRF Token request gives me errors.
Could someone possibly point out where I am going wrong here, the Appgyver site is badly documented and I have tried the Angular RESTful sample which my code below is based upon from https://docs.angularjs.org/api/ng/service/$http and https://docs.angularjs.org/api/ng/service/$http#setting-http-headers
Please note the code below is basically Angular.js using Javascript syntax (as opposed to Coffeescript), logging output follows the code
angular
.module('main')
.controller('LoginController', function($scope, supersonic, $http) {
$scope.navbarTitle = "Settings";
$scope.stoken = "Response goes here";
$scope.processLogin = function(){
var csrfToken;
steroids.logger.log("START CALL: processLogin");
// $form_login_email_address = $scope.login_email;
// $form_login_password = $scope.login_password;
$local_get = "http://somesite.com/quote-and-buy-performance/services/session/token";
$hal_get_taxterm_index = "http://somesite.com/quote-and-buy-performance/druidapi/taxonomy_term";
// $http.defaults.headers.common.contentType('application/json');
var req = {
method: 'GET',
url: $hal_get_taxterm_index,
headers: {
'Content-Type': 'application/json'
}
}
$http(req)
.success(function(data, status, headers) {
steroids.logger.log("Inside http.get() success");
}).error(function(data, status, headers){
steroids.logger.log("Inside http.get() WITH ERROR");
steroids.logger.log('data: ' + data);
steroids.logger.log('status: ' + status);
}).then(function(data, status, headers){
steroids.logger.log("Inside http.get() then");
});
steroids.logger.log("END CALL: processLogin");
}
});
Logging output from calls to steroids.logger.log
View Time Level Message
main#login 16:01:55.219 info "Inside http.get() WITH ERROR"
main#login 16:01:55.219 info "data: null"
main#login 16:01:55.219 info "status: 0"
main#login 16:01:55.64 info "END CALL: processLogin"
main#login 16:01:55.64 info "START CALL: processLogin"
Here's what I would do:
Separate out your http call into a service. This is a pretty standard way to modularize your code in angular:
angular.module('main').factory("SomeService", function($http) {
return {
get: function() {
$http({
url: "http://somesite.com/quote-and-buy-performance/druidapi/taxonomy_term",
method: "GET",
headers: {
"Content-Type": "application/json"
}
}).success(function(data, status, headers, config) {
console.log("Success!");
console.log(data);
}).error(function(data, status, headers, config) {
console.log("Error!");
console.log(status);
console.log(data);
});
}
}
})
Then to use this in your controller, just include it in your controller declaration and call get like you would a normal method:
angular.module('main').controller('LoginController', function($scope, supersonic, SomeService) {
$scope.navbarTitle = "Settings";
$scope.stoken = "Response goes here";
$scope.processLogin = function(){
var csrfToken;
steroids.logger.log("START CALL: processLogin");
SomeService.get();
steroids.logger.log("END CALL: processLogin");
}
})
Do this and then comment back with your results and we can work from there.
If your angular's app is within a certain domain, then HTTP request must be made within the same domain.
In your case, you are trying a cross domain request (a request on another domain). You must then make a cross domain request.
You can see this question.
The author uses $http.jsonp() to send cross domain requests. There migth be another way to do it.

Cross Domain request returns status code 0 in Firefox but 200 in Chrome

I have code in a directive that is making a cross domain request. When it runs in Chrome, it works just fine. When it runs in Firefox or IE 11, I get a status code of 0 with no data. My code is:
$http({method: 'GET', url: 'https://mycrossdomain.url'})
.success(function(data, status, headers, config) {
alert('success');
})
.error(function(data, status, headers, config) {
alert('error');
})
In Firefox and IE I get "error" alerted and in Chrome I get "success" and I can view the data.
Why would this be happening? The server obviously supports cross domain requests because it works in Chrome. When I navigate to the URL in all browsers I get a response so it definitely exists. Any help would be appreciated.
Turns out the issue was that I needed to specify withCredentials like so:
$http.get('https://mycrossdomain.url', { withCredentials: true})
.success(function(data, status, headers, config) {
alert('success');
})
.error(function(data, status, headers, config) {
alert('error');
})
This is because I needed to pass the user credentials (a certificate) to the other domain. Angular was unfortunately not providing very useful error messages.

Getting JSON data using Angular JS's $http service

I need to get JSON data from a server with URL :
http://xxxx.xxxx.xxxx.xxxx:8084/inpulse/api/user/listall
Here's my angular code:
var app = angular.module('app',[]);
app.controller('Controller', function ($scope,$http) {
$scope.email="";
$scope.password="";
$scope.sample="";
$http({
method: 'GET',
url: 'http://xxxx.xxxx.xxxx.xxxx/inpulse/api/user/listall',
})
.success(function (data, status, headers, config) {
var ret = data;
$scope.sample = JSON.stringify(ret);
})
.error(function (data, status, headers, config) {
alert(status);
// something went wrong :(
});
});
Now the same code worked when i used a JSON test URL like http://ip.jsontest.com/.
Its Definitely not a problem with the server because I tested it with a REST client and got a response. I can't figure out what I'm doing wrong.
It might be a CORS configuration issue.
If you are trying to access the server from a page that is not in the same domain/origin, you'll get an error because the server is not configured to allow CORS.
The error reported by Chrome looks like this:
XMLHttpRequest cannot load http://xxxx.xxxx.xxxx.xxxx/inpulse/api/user/listall. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://fiddle.jshell.net' is therefore not allowed access.
Other than that the code seems to work just as expected.

Angular JS Custom Headers on GET Turns to Options

So, this has been a huge struggle for us.
We have a web API .net MVC4 back-end. We are using angular for client-side. We have a page that has some JSON that we receive data from. When we make a GET to this page we receive data. As soon as we add custom headers to the call the GET turns into OPTIONS and we get a 200, with no response. We are doing a couple things like creating a BASE64 code on "login" storing it as a cookie and trying to add that to the GET headers. the thing is we have stripped out all of the unnecessary code and we are still at the same problem. Even with authorization turned off for the data. Here is the GET code:
myApp.factory("projectDataService", function ($http, $location, $cookieStore) {
var token = "";
token = $cookieStore.get('token');
return {
getProject: function (successcb) {
$http({ method: "GET", url: "http://dev.projnik.com/api/project", headers: { 'Authorization': 'Basic ' + token } }).
success(function (data, status, headers, config) {
successcb(data);
}).
error(function (data, status, headers, config) {
console.log(data, status, headers, config);
});
},
save: function (project) {
$http({ method: "POST", url: "http://dev.projnik.com/api/project", data: $.param(project) }).
success(function (data, status) {
if (status == '201') {
$location.path('/all');
}
})
}
};
});
And the app.js:
var myApp = angular.module('Project', ['ngResource', 'ngCookies']);
myApp.config(function($routeProvider){
$routeProvider.
when('/new', {templateUrl:'templates/new.html', controller:'EditProjectController'}).
when('/mobile', {templateUrl:'templates/mobile.html', controller:'ProjectController'}).
when('/it', {templateUrl:'templates/it.html', controller:'ProjectController'}).
when('/writing', {templateUrl:'templates/writing.html', controller:'ProjectController'}).
when('/all', { templateUrl: 'templates/all.html' }).
when('/cookie', { templateUrl: 'partials/cookiecontrollerhtml.html' }).
when('/login', { templateUrl: 'partials/_login.html' }).
otherwise({ redirectTo: '/all' });
});
myApp.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}]);
Again, without adding headers attribute to the call, everything works (obviously we get a 401 with Authorization turned on in the API). We are willing to pay for an answer at this point.
We are exposing our actual domains here, and that is fine. If someone goes to www.projnik.com and clicks the login link on the top and enter shane, password for username,password they would receive the cookie and it routes the user back to the #/all page where they would GET the data, though it doesn't work.
PS: I have tried to ad withCredentials = true; to the call and I get the same result.
If you are accessing API in dev.projnik.com from a web page in www.projnik.com, in a browser like Chrome, CORS comes into play. If you make a GET without any custom headers, it is a simple CORS request and I assume you have settings in web.config that sends Access-Control-Allow-Origin header and that makes it work. Once you add a custom header, it is no longer a simple CORS and it becomes pre-flighted CORS with browser making an OPTIONS request. The response to this OPTIONS request must send the correct CORS headers for the browser to make the subsequent GET. To enable CORS, check this out. BTW, in IIS there is a default handler that answers OPTIONS call that you might need to remove for the message handler in Web API to respond to OPTIONS.
I am working with Shane on this - the block of code on the server is:
public void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
//These headers are handling the "pre-flight" OPTIONS call sent by the browser
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}
I believe this takes care of the situation. But the problem is still there.

Resources