0

I am developing an application using ember.js which is running over node.

Now, I have to call some external webservices and construct my home page accordingly (based on the webservice response).

  • These webservices are running in some external server (different domain). Currently I am running my website from a local environment.
  • Authentication: Only after providing a valid credentials, user can access these webservices. That is, If I try to access this webservice from a browser, first it will ask to provide a username and password. If these credentials are valid (server side validation), it will return a response json.

My app.js code is as follows:

var express = require('express');
var routes = require('./routes');
var http = require('http');
var path = require('path');

var app = express();

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.cookieParser('your secret here'));
app.use(express.session());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

// development only
if ('development' == app.get('env')) {
    app.use(express.errorHandler());
}

app.get('/', routes.index);

http.createServer(app).listen(app.get('port'), function(){
    console.log('Express server listening on port ' + app.get('port'));
});

Home page code (for simplicity, I have removed all its view and just calling my external webservice on page load)

<html>
<head>
    <title>Lets think..</title>
    <script src="./javascripts/libs/handlebars-1.0.0.js"></script>
    <script src="./javascripts/libs/jquery-1.9.1.js"></script>
    <script src="./javascripts/libs/ember-1.1.2.js"></script>
    <script>
        window.App = Ember.Application.create();
    </script>

    <script>
        $(window).load(function(){
            $.ajax({
                type: 'GET',
                url: 'http://vpn.domain_name.com/myServer/WebService/json/getInfo',
                data: {username: "user_name",password: "my_password"},
                success: function (data) {
                    console.log('sucess');
                },
                failure: function(error){
                    console.log('error');
                }
            });
        });
    </script>
</head>
<body>

</body>
</html>

As said above, I was able to access the below webservice (http://vpn.domain_name.com/myServer/WebService/json/getInfo) successfully from a browser (after credentials validation).

However, when I try to access it through code, I am retrieving the below error: On debugging through firebug:

"NetworkError: 401 Unauthorized - http://vpn.domain_name.com/myServer/WebService/json/getInfo?username=user_name&password=my_password"

On debugging through Google Chrome console:

XMLHttpRequest cannot load http://vpn.domain_name.com/myServer/WebService/json/getInfo?username=user_name&password=my_password. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.

I am not sure whether the above errors are due to cross domain access or http basic authentication error.

I tried with solutions suggested in How to allow CORS? and http://nthloop.com/blog/local-dev-with-nodejs-proxy/

However, I was not able to retrieve a proper response from my code. Can anyone please guide me on this.

Thank You.

Community
  • 1
  • 1
  • 1
    Use Jsonp instead of ajax. Check http://stackoverflow.com/questions/5943630/basic-example-of-using-ajax-with-jsonp – Damodaran Nov 25 '13 at 12:45
  • Thanks Damodaran.. Once after the addition of -- dataType: 'jsonp' in my ajax call, I am able to retrieve the response successfully. Thanks for that. However, now I am getting another strange issue. First time when I run my application (website), it asks me to provide the webservice's username and password on page load.. once after I provide the valid credentials, I am able to access website successfully. How can I remove this authentication request. In other words, I am passing these credentials (user_name and password) in my ajax call. Why its not affecting? Suggestions please. Thanks again. –  Nov 25 '13 at 13:51

2 Answers2

1

(more an answer to the comment, not the actual question)

If you want to pass login credentials for basic authentication using $.ajax:

$.ajax({
  type      : 'GET',
  url       : 'http://vpn.domain_name.com/myServer/WebService/json/getInfo',
  username  : 'user_name',
  password  : 'my_password',
  success   : function (data) {
    console.log('success');
  },
  failure   : function(error){
    console.log('error');
  }
});

(instead of passing username and password as URL parameters with data).

Community
  • 1
  • 1
robertklep
  • 198,204
  • 35
  • 394
  • 381
  • Thanks for the reply. As Damodaran replied above, after using dataType: 'jsonp' in ajax call, I am able to retrieve the response successfully.However, when I run my application, it asks me to provide the webservice's username and password for the first time - on page load (basic authentication). once after I provide the valid credentials, I am able to access website successfully.How can I remove this first time authentication request. In other words, I am passing these credentials (user_name and password) in my ajax call itself.Then why I am requested to provide credentials for the first time –  Nov 25 '13 at 14:06
  • @Kamal did you notice how my code differs from your original code? – robertklep Nov 25 '13 at 14:10
  • I got the same error when I pass username and password as URL parameters with data or when passing them separately - as mentioned by you :( Only when I included dataType: 'jsonp' in my ajax call, this issue is fixed. However, getting the first time authentication issue. –  Nov 25 '13 at 14:16
  • @Kamal have you created the webservices yourself? if so, can you show the code that handles the authentication? – robertklep Nov 25 '13 at 14:27
  • No. I haven't created these webservices. Also, I don't have access to this webservices code. Sorry. I feel the basic http authentication which given above are correct. I think, requesting username and password should be only of basic http authentication type. please correct me if I am wrong. –  Nov 25 '13 at 19:34
  • 1
    @Kamal I tested the code with a basic authentication framework and it works okay. It might be that the web service falls back on some other form of checking the authentication when the request is performed using JSONP, but I'm just guessing here... – robertklep Nov 25 '13 at 19:49
  • Thanks. I will check with the author of this webservice to find the reason. Also, I am using JSONP only to handle the cross domain issue. However, I have this first time basic authentication issue and response issues (SyntaxError: missing ; before statement in my response element). I found from the below link that: http://stackoverflow.com/questions/19456146/ajax-call-and-clean-json-but-syntax-error-missing-before-statement, if we use JSONP instead of a JSON, we will get this issue. So I feel, this webservice is not supporting JSONP. I am looking for an alternative solution. Can you guide me –  Nov 25 '13 at 20:05
  • 1
    @Kamal if the webservice doesn't support JSONP *or* CORS, you're pretty much out of luck, unless you set up a local proxy to it. – robertklep Nov 26 '13 at 08:35
  • Yes, you are correct robertklep. I used http-proxy and now everything works fine. Included my code below. Thanks. –  Nov 26 '13 at 10:20
1

I have initially used JSONP, because it is really a simply trick to overcome XMLHttpRequest same domain policy. However, the webservices which I am accessing raised few issues with JSONP data type (basic http athentication fails for first time and response throws a strange error SyntaxError: missing ; before statement). As I don't have much control over webservices to work with JSONP, thought to drop JSONP option and proceeded with http-proxy method way of handling the cross domain issue.

Made following changes in client code and now I was able to access webservices successfully.

(1) Installed http-proxy npm

(2) Added following lines in app.js

var httpProxy = require('http-proxy');

var endpoint  = {
    host:   'IP_ADDRESS_OR_DOMAIN_NAME', //of webservice
    port:   80, 
    prefix: '/myServer/WebService/json'  //all my webservices are accessed through this path
}

app.use(function(req, res) {
    if (req.url.indexOf(endpoint.prefix) === 0) {
        proxy.proxyRequest(req, res, endpoint);
    }
});

(3) My ajax call will be:

$(window).load(function(){
            $.ajax({
                type: 'GET',
                url: '/myServer/WebService/json/getInfo',
                username: "user_name",
                password: "password",
                success: function (data) {
                    console.log('sucess');
                    console.log(data);
                },
                failure: function(error){
                    console.log('error');
                }
            });
        });

Here: /getInfo is the webservice (with basic http authentication).

Hope this helps!

Thanks.