#! fallback for POST requests - angularjs

I am using angular 1.2
I have configured
$locationProvider.hashPrefix('!');
$locationProvider.html5Mode(false);
When using IE8 and IE9 I got two requests:
POST /base/action
GET /base/#!/action
So parameters from the first post are tragically lost...
The simple solution is just to send POST /base/#!/action on ie8 and 9 (so there is no redirection), but since this is partially out of our control.
I was wondering if there is a solution to send a POST for the request 2., even if some server side processing (for example to expose in JS POST data) is needed.
EDIT:
Some more details on the scenario. I am talking about the first request we get to our site. The request is done by a third party, and it must be done using POST. As a result the user should see the first page of our angular application. I am not talking about a request made with $http, and this is not a call to an API. The expected result is an HTML page. The POST request is coming from another page, using "classical" form submit method.

I finally decided to use fallback mode #! on all the borwsers, so I do not have this issue and I keep things simple.

Related

Ionic 3 InAppBrowser capture request Pre Load

I am utilizing inAppBrowser and understand how to subscribe to event observable such as loadstart, loadstop etc. I am trying to figure out a solution for capturing the request made from within InAppBrowser instance previous to it being sent, similar to Angulars HTTPInterceptor feature when making crafted requests from within the app it's self.
As I understand it, loadstart has already committed to sending the request and all you can capture from this is the URL from within Ionic app.
As a solution I can executescript and utilize its callback to retrieve info about a request direct from the browser but this feels like a awkward solution.
Any alternate solutions or assistance would be greatly appreciated.

Passport.js, Express.js, and Angular.js routing: how can they coexist?

I apologize this question turned out a bit long, but I have worked on this for some time and really needed to explain all the story.
Background: App based on MEAN stack, trying to authorize Facebook logins using Passport.js.
Following Passport.js guide I implemented something similar to:
// HTML
Add a Facebook login
// send to facebook to do the authentication
app.get('/connect/facebook',isLoggedIn, passport.authorize('facebook',
{ scope : 'email' })
);
// handle the callback after facebook has authorized the user
app.get('/connect/facebook/callback',
passport.authorize('facebook', {
successRedirect : '/profile',
failureRedirect : '/profile'
}));
Notice the target=_self in the html in order to skip Angular routing.
Clearly, authorization works fine. However, redirection does not work, as the routing is handled by Angular. After authorization I never land on /profile (but on the default Angular route).
Therefore, I tried with a custom callback as suggested by Passport.js here, with the hope of passing json data to Angular, and let Angular do the routing. I ended up doing something like:
// In the controller
$http.get("/connect/facebook").success(function(data){
// here I wait for json data from the server and do the routing
});
// I call this route from Angular
app.get('/connect/facebook',isLoggedIn,passport.authorize('facebook',
{ scope : 'email' })
);
// But Facebook lands here!
app.get('/connect/facebook/callback',function(req, res, next) {
passport.authorize('facebook', function(err, user, info) {
res.json({something:smtg});
...
Clearly custom callbacks work for local-login, as Passport.js explains. But here do you see the problem? I call /connect/facebook from Angular, but I should receive some json from /connect/facebook/callback.
I am about to give up Passport, but before this, do you see any solution which would allow landing on /profile after FB authorization, perhaps with a custom message? Many thanks for reading through.
EDIT:
The same question had been reported as an issue on the Passport-Facebook GitHub account. Some additional attempts have been posted there, but not quite the fix yet.
This is a bit more in depth than can be described in one answer, but I'll try to start pointing you in the right direction.
Essentially, Angular.js routes are not really HTML routes at all, but an internal route structure that happens to use the URL for use of the end user. Remember that Angular.js is a client script, and that a full page reload is not desired, as this will reload the entire script. Therefore, /# is used to trick the browser into jumping to a specific bit of code within the already loaded script. (as opposed to the traditional anchor location in the HTML document). Unfortunately (or fortunately), HTML 5 mode allows you to hide the /# part of the url, so instead of seeing http://somesite.com/#/someroute you just see http://somesite.com/someroute. Rest assured, however, that the /# is still there. Angular.js uses the HTML5 pushState (AKA HistoryAPI) to perform the magic replacement.
Given this, if you have called a server route, you are outside the Angular.js script, and any call to load the angular script again will start from the very beginning. You can't actually call your Angular.js route from the server without a full reload. Therefore, you are really doing a double route redirect here. Your server should be calling it's default route for angular, appending /#/someroute to the call. The angular.js page will load, parse off the /#, and redirect to the correct angular route. Keep in mind, however, that if there was any dependency on already loaded objects, those are no longer in memory. Therefore, any route accessed this way should operate as if it is an entry point to your application.
Effectively, you should try using successRedirect : '#/profile', keeping in mind that the profile route in angular should be treated as an app entry point.
Hopefully this gets you started.
If #Claies's way is not working, is it possible you have not get rid of the #= fragment from the facebook callback.
Have a read of this post

AngularJS + Domain/URL Redirect not working well together

I got a small angularJS based website.
I am hosting it via the service OpenShift on some domain like:
bla-blubb.rhcloud.com
Which is of course not that pretty, so I ordered a TLD:
www.supercoolsite.com
from www.united-domains.de. There I habe three possibilities to achieve my goal, see the screen (sorry it is in German - it is: 1) Header redirect, 2) Frame-redirect or 3) URL-Hiding)
But none of these seem to work like I want:
1) Simply redirects the user, so the ugly URL is shown again.
2) Shows my pretty URL, BUT I can't type in like /#/stuff/some/page, it simply does nothing and remains on the start screen. My ngRoute $routeProvider's .when() doesn't trigger that URL like it normally does.
3) Here everything works just fine. I can use Angualr as I'm used to, the above error disappears + the URL is still pretty. BUT: Now I can't send POST Requests with payload to my Java Spring MVC Backend. I get an 415 Error (See second Screen). When using the ugly URL it works perfectly (Everything). It also works using GET methods.
The server refused this request because the request entity is in a format not supported by the requested resource for the requested method.
Does anyone might have an idea? How can I get 2) or 3) working? I don't get what's going wrong.
If code (angular or Spring Controller) is needed, tell me - but as said, it works under DEV and when using the ugly URL.
Thanks!!
A solution for me was to use another (sub) domain like admin.supercoolsite.com, which does a frame redirect to the /#/stuff/some/page URL, automatically triggering my intended behavior.

AngularJS getting data from backend

I would like to know what is the proper way to get data from backend when I want to use angularJs (or similar) in my web app?
The only way I see is to render html (static html with js scripts - e.g. angularjs) with no data from backend and then download data via ajax requests from my backend API. But I think this solution is not good because of many HTTP requests:
For example I have blog website, I want to show a post, comments, and the related posts on the sidebar. So probably I need to make at least 3 HTTP requests to get the data unless I will prepare API to get all I need in one request.
I can also imagine websites that could have much more HTTP requests. Is it a proper way to do this? Doesn't it overload a server? Or my way of thinking is so wrong?
It is either websockets or HTTP requests. Preparing API to get all in one request is one option. Another two options are XMLHttpRequest/iframe streaming which is a method of a technique known as Comet.
I would go with websockets since it is supposed to solve the problem that was previously solved with weird applications like iframe streaming. There are libraries that properly handles fallbacks if the browser does not support websockets:
web-socket-js ( this needs a websocket server )
Socket.IO ( this has a node.js module and also implements a kind of unnecessary protocol on top of websocket protocol )
If you choose the old methods there will be many problems waiting for you on the road like XmlHttpRequest.responseText while loading (readyState==3) in Chrome
I think you have to distinguish two cases:
You render the page for the first time.
You update parts of your page when something changes
Of course in the second case it makes sense to fetch only parts of the page via individual HTTP requests. However, in the first case you can simply serialize your complete model as one JSON object and embed it in the page like this:
<script type="text/javascript">
var myCompleteModel = { /* Here goes your model */ };
<script>
The controllers of the components on your page can then access this global variable to extract the parts being relevant for them. You can also wrap access to the initial model in a service to avoid accessing a global variable in all your controllers.

AngularJS $http not sending GET request

In an Angular JS app I'm working on, I am using a service to periodically (in a $timeout) make a GET request to a URL in my API (both the Angular app and the API are being served from port 5000 on localhost).
For some reason, it appears that $http is not actually sending the GET. For each $http.get(), the .error() is called with empty data and a status of 0. When I check in my server log (I'm running a Ruby on Rails backend with the Unicorn gem for my server), it appears that the server never receives the request from Angular.
Here's the function in my service:
updateUserStatus = () ->
$http.get('/api/v1/status').success (statusData) ->
# update the variable and notify the observers
this.userStatus = statusData
notifyObservers()
startStatusTimeout()
.error (error, status) ->
# if there's an error, log it
console.log 'error:'
console.log error
console.log status
startStatusTimeout()
What's really odd is that it only happens sometimes. When it stops working, I can change the URL in the $http.get() to '/api/v1/status.json', and it works. For a while. Then I switch it back and it works again, for a while... obviously there is some greater issue at play.
I've been racking my brain for a few days now, and I've seen a bunch of similar issues on SO, but they all seem to be solved with implementing CORS in Angular, which I don't think is applicable to my situation because it's all coming from localhost:5000. Am I wrong? What's going on?
For reference, I'm using Angular version 1.0.7.
I had the same problem.
Check your code to see whether this happens after events that are fired from the DOM and are unknown to Angular.
If so, you need to add $scope.$apply(); after the get request in order to make it happen.
I'm fairly new to Angular so I'm not sure this is the best practice for using Angular, but it did work in my case.
See this similar question for a better explanation.

Resources