I've a simple angularjs application like:
module = angular.module 'testFooBarModule', ['ngResource']
module.factory 'FooBar', ($resource)->
$resource 'foobar/target', {},
load:
method: 'GET'
cache: false # no effect
headers:
'Cache-Control': 'no-cache' # no effect
module.controller 'FooBarCtrl', ($scope, FooBar)->
FooBar.load (result)->
console.log result
With highspeed internet like home wlan or mobile hspa everything works fine. The request has fired and the server gives me a unique response.
But with 2G internet like edge or gprs the server receives no requests and the angularjs app give me always the same results. No errors occur. The "no-cache" header were sended as well.
I've no idea what's wrong. Can anyone help me?
Sry for my english :D
best regards.
Thats probably not an angular issue. My guess is the internet-provider is doing some magic http-proxying to safe bandwidth or your underlying OS is trying to cache it for you.
Some options:
using HTTPS should prevent provider man-in-the-middles and for mobile apps in any case a good idea!
using a clumsy dynamic parameter like a timestamp
use POST or PUT as verbs
add the 'Cache-Control: no-cache' header in the server-response, which I think the is the most-clean solution
Related
I'm kind of new to angular, and it's the first time I'm using $http.put.
My problem is when I send the packet, it won't include the data (json object), and the PUT is a header(?).
This is what my code looks like:
app.controller('StatusController',['$http', function($http) {
this.updateComment = function (eventid, comment) {
var requestData = {"event-id":eventid, "new-comment":comment};
$http({
method: 'PUT',
url: "http://172.18.212.59/event",
data: requestData,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
});
}
}
So I used Fiddler to generate a PUT request to the server, and it worked. so I looked at the packets, trying to understand where the differences come from...
Here are the results:
Packet generated by Angular - Not working
Packet generated by the Fiddler Composer - Working
Also I've tried using:
$http.put(url, requestData)
But that didn't work either... My GET requests work perfectly fine! And they look like the packet that does work...
Has anyone encountered this problem before?
Appreciate your help!
OPTIONS verb is used when doing cross domain requests. Basically you need to enable cross domain requests on your server side code. The GET request works cause it isn't protected by cross domain restrictions and Fiddler works cause cross domain requests comes into picture when making XHR requests from browser. If you look into the response to the OPTIONS request you will probably find something saying cross domain request not allowed.
I'm trying to interrogate a rest service. If I use CURL I can get the data back without issue.
curl -k -X GET -H "Accept: application/json" -u username:password "https://example.com/v1/apps"
However, I've tried several methods for pulling data back using Angular's $http and $resource services and nothing seems to work.
Does anyone have a good example of how to do this with Angular 1.4.6?
It's both a Cross-Domain and Basic Authentication call.
There are so many "like" examples out there, but nothing seems to work.
Hopefully this will save someone else some frustration. A few things were causing the issue.
The certificate on the target site was invalid. They were using a self-signed cert with example.com as the domain.
The call I was using had a capital 'GET' in it, it should be all lower-case.
To solve issue 1, I had to add the server's IP to my hosts with an alias example.com. It's a major hack, but it was necessary to get around the invalid domain issue. I'm working with the server's owners to have a correct cert put in place.
For the call itself, here an example that works. I'm using another service for the auth header. It just base64s the username and password. Replace AuthorizationService.getCredentials() with your favorite base64(username:password) tool. There are several of them out there.
.factory(
'ApplicationDetailService',
[
'$resource', 'AuthorizationService',
function($resource, AuthorizationService) {
return $resource('https://example.com/v1/apps/:id', { id: '#id' },
{
'get' : {
headers: {
Authorization: AuthorizationService.getCredentials()
}
}
}
);
}
]
)
Finally, because the target server wasn't passing back the Access-Control-Allow-Origin: * header in its response. All of the modern browsers to flat out reject the AJAX return.
I was under the assumption that it was an Angular thing, I was wrong. There's a plug-in for Chrome called Access-Control-Allow-Origin: *, I tried that, it failed because CORS needs your domain in the header.
I found a flag for chrome --disable-web-security that tells Chrome to ignore all security. FAIR WARNING: This makes your session very insecure. Only do this for a test environment. Just modify your shortcut to pass the flag in as a parameter to chrome.exe.
With all of that, I was able to get past my issue and continue developing until the server team fixes things on their end.
Best of luck!
I am currently using MEAN stack for web development. My questions is how do I mix/redirect HTTP and HTTPs pages on the same website?
For most scenarios I am communicating with the back-end using HTTP protocol. And for some pages I absolutely need to use HTTP (For example /shop route I used a iframe that displays info from other websites. Also for some pages I need to HTTP GET from other API services providers.). It seems that I cannot achieve these with HTTPs setup.
For some cases I am communicating with the back-end using HTTPs (such as /money route) ...etc. And apparently you need HTTPs with money involved.
My back-end has middlewares setup so that if you request /money using HTTP it will return some error (currently returning 301 moved permanently..)
But I am not sure how do I proceed with front-end development. For Angular part should I just do some configurations so when the route consists of /money I just reload the whole page in HTTPs and should I just explicitly make sure the links look someting like this?
<a ng-href="https://www.domain.com/#!/money">money page</a>
But that seems like a lot of hard-coding for me.
My question is:
1. Am I thinking in the right direction?
2. Is it doable?
Thanks and any idea is greatly appreciated!
There are a few things to consider here.
First of all, yes, when money is involved you should always use HTTPS. The S here stands for secure, so as you can imagine this means that regular HTTP is not secure. With regular HTTP things are sent in plain text, so anyone who can see the request along the way can see and copy what's in there. For this reason you should always make sure to use HTTPS if you are doing things like sending financials data, sending passwords/login requests, sending private user data, etc.
You should also remember that you shouldn't load HTTP content on a HTTPS page, this will cause browsers to warn for insecure content or even block the request outright.
Anyway, on to the actuall question. Yes, you are thinking correctly. When going from HTTP to HTTPS you are going to have to do a full reload of the page, but hardcoding https into any such link is not a great solution. Luckily Angular provides us with decorators for directives that allows us to chainge their behavior. You can use this to decorate ngHref so that it adds https on it's own when certain conditions are met.
Decorators are not that easy to get started with however, or at least they weren't the last time I read the docs, so here is one that does what you need and that you can edit to cover more cases:
myApp.config(function($provide) {
$provide.decorator('ngHrefDirective', function($delegate) {
var original = $delegate[0].compile;
$delegate[0].compile = function(element, attrs, transclude) {
if(attrs.ngHref.indexOf('money') !== -1) {
attrs.ngHref = 'https://example.com/'+attrs.ngHref;
}
return original(element, attrs, transclude);
};
return $delegate;
})
});
This will take any ng-href directive that contains the word money, and change the input data to include the full path with https. It will turn this:
<a ng-href="/money">Link that should be re-written</a>
<a ng-href="/other">Link that should not be re-written</a>
Will become this:
<a href="https://example.com/money>Money link</a>
Link that should not be re-written
I have the following in my Angular Model:
return Restangular.all('user/session/authenticate').post({user_id: user_id, password: password});
Which I call in my controller:
User.authenticate($scope.user.userId, $scope.user.username)
.then(function (authToken) {
//do stuff
};
But, it never makes a request. The headers are created, the data is there, and there is no error. I know it's probably me, but for the life of me, I can't figure out what. Also, I can successfully make GET requests to the same service.
Well, the problem wasn't me...sort of. I had the correct Restangular syntax, but a lack of understanding of how my browser works. The browser wanted me to confirm a security exception. No error was given, until I put the url directly into the url bar in FireFox.
Once I confirmed the security exception, the requests began to work.
I am trying to get a basic $resource request via angularjs. I am running this on my local computer.
However, I get a 404. A simple get request on the browser loads the json.
Here is the request shown by chrome devtools. (Question: why is the request mode: OPTIONS? Could that be the problem?)
Request URL:http://example.com/api/rentable_properties.json
Request Method:OPTIONS
Status Code:404 Not Found
Here is my controller that is attempting to make the request:
'use strict';
angular.module('adminApp')
.factory('Property', function($resource)
{
return $resource('http://example.com/api/rentable_properties.json/:propertyId');
});
angular.module('adminApp')
.controller('PropertiesCtrl', function ($scope, Property, $location) {
$scope.properties = Property.query()
The answer here is that your browser is running into a cross domain issue
See http://metajack.im/2010/01/19/crossdomain-ajax-for-xmpp-http-binding-made-easy/ for an explanation and Why am I getting an OPTIONS request instead of a GET request? for a question basically the same as yours.
As mentioned by #JSager, the problem was a cross domain issue.
Since I had control over the server side (running a Rails server), I had to change the server to it to receive cross-site requests.
In my case, I had to install a gem and follow it's instructions.
https://github.com/cyu/rack-cors
This fixed the issue for me. No changes made on the Angularjs based app.