Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

AngularJS: How to call API on a remote server

Posted on 2015-02-19
7
366 Views
Last Modified: 2015-02-20
Hi, I am separating an AngularJS App with Slim PHP API onto 2 servers.
The full app is here: dev02.photomonkey.ch (A)
The new frontend is here: dev03.photomonkey.ch (B)

(donwload link for entire app: http://www.angularcode.com/download-link/?url=https://app.box.com/s/pqr0wo3osvoahyh7qtsa)

It turns out the backend is working, ie when I call http://dev02.photomonkey.ch/api/v1/products directly from the browser I get the JASON Data.
However when the app on dev03.photomonkey.ch wants to get data, it issues the following GET: http://dev03.photomonkey.ch/api/v1/products
How can I get the data factory to call a different endpoint?
$http gets injected by angular, can it be changed in the data.js?
How is this generally done when a frontend needs to call a backend on a remote server?
Thank you!


NOTE: Changing var serviceBase = 'api/v1/'; to anything else will still get a 404, as that path just gets appended to the endpoint which is http://dev03.photomonkey.ch, but needs to be http://dev02.photomonkey.ch

*************************************
.htaccess
*************************************

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ %{ENV:BASE}index.php [QSA,L]


*************************************
data.js
*************************************

app.factory("Data", ['$http', '$location',
    function ($http, $q, $location) {

        var serviceBase = 'api/v1/';

        var obj = {};

        obj.get = function (q) {
            return $http.get(serviceBase + q).then(function (results) {
                return results.data;
            });
        };
        obj.post = function (q, object) {
            return $http.post(serviceBase + q, object).then(function (results) {
                return results.data;
            });
        };
        obj.put = function (q, object) {
            return $http.put(serviceBase + q, object).then(function (results) {
                return results.data;
            });
        };
        obj.delete = function (q) {
            return $http.delete(serviceBase + q).then(function (results) {
                return results.data;
            });
        };
        return obj;
}]);




*************************************
Entire APP on dev02.photomonkey.ch
Use this only as the backend! (A)
*************************************

webroot of dev02.photomonkey.ch
|   index.html
|  
+---api
|   +---libs
|   |   \---Slim
|   |       |   Environment.php
|   |       |   etc
|   |       |  
|   |       +---Exception  
|   |       +---Helper    
|   |       +---Http
|   |       \---Middleware
|   \---v1
|           .htaccess
|           config.php
|           dbHelper.php
|           index.php
|          
+---app
|       app.js
|       data.js
|       directives.js
|       productsCtrl.js
|      
+---css      
+---fonts    
+---js    
\---partials

*************************************
New frontend dev03.photomonkey.ch (B)
*************************************
webroot of dev03.photomonkey.ch
|   index.html
+---app
|       app.js
|       data.js
|       directives.js
|       productsCtrl.js
|      
+---css      
+---fonts    
+---js  
\---partials
0
Comment
Question by:jacobs99
  • 4
  • 3
7 Comments
 
LVL 11

Expert Comment

by:Radek Baranowski
ID: 40620020
Hello again

as I told you, this is probably CORS problem, that means that your service on dev02 is not Cross-domain enabled.

The link with description has been posted in the other question.

If you launch you page in Chrome (from dev03) but press F12 before to track network traffic for this session you will see that trying to get data from dev02 ends with XMLHTTPRequest failing due to Cross-origin limitation. That's why I'm saying this is CORS problem.
0
 

Author Comment

by:jacobs99
ID: 40620057
Hi Radek,
I am sorry. With all due respect, please consider that you may be on the wrong track.

Clicking the GET in the Chrome-F12-network and clicking the header tab shows that in fact it is trying to reach http://dev03.photomonkey.ch/api/v1/products which does not have the API exactly as explained in the question.

I am looking for an answer to the question: How to get the $http angular object to point to the correct endpoint.

I have no expertise whatsoever in Angular.

Thank you
0
 
LVL 11

Expert Comment

by:Radek Baranowski
ID: 40620115
Yes and hence 404 error.

If you set serviceBase to http://dev02...  on dev03 in data.js you will see XMLHTTPRequest error in Chrome F12 network debug.

Url param for $http object is set as serviceBase + q where q is 'products' and together they form Url which yields you 404 error instead of timeout/invalid response

But yeah i can be on the wrong track of course.
0
Space-Age Communications Transitions to DevOps

ViaSat, a global provider of satellite and wireless communications, securely connects businesses, governments, and organizations to the Internet. Learn how ViaSat’s Network Solutions Engineer, drove the transition from a traditional network support to a DevOps-centric model.

 

Author Comment

by:jacobs99
ID: 40620631
I set the following in the htaccess file on dev02 and am now able to execute a GET from dev03 to dev02:

# Cross domain access
Header add Access-Control-Allow-Origin "*"
Header add Access-Control-Allow-Headers "origin, x-requested-with, content-type"
Header add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"

However, POST, PUT and DELETE do not work (yet!)
0
 
LVL 11

Accepted Solution

by:
Radek Baranowski earned 500 total points
ID: 40620690
I can see now this:

"XMLHttpRequest cannot load http://dev02.photomonkey.ch/api/v1/products. The 'Access-Control-Allow-Origin' header contains multiple values 'http://dev03.photomonkey.ch, *', but only one is allowed. Origin 'http://dev03.photomonkey.ch' is therefore not allowed access."

So you would probably need to leave only '*' out there.
0
 

Author Comment

by:jacobs99
ID: 40620694
I added the following to the index.php. Removed the header add from htaccess.
Tested GET, PUT, POST and DELETE. All working so far.

if (isset($_SERVER['HTTP_ORIGIN'])) {
        header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
        header('Access-Control-Allow-Credentials: true');
        header('Access-Control-Max-Age: 86400');    // cache for 1 day
}

if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']) && (  
       $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] == 'POST' ||
       $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] == 'DELETE' ||
       $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] == 'PUT' )) {
             header('Access-Control-Allow-Origin: *');
             header("Access-Control-Allow-Credentials: true");
             header('Access-Control-Allow-Headers: X-Requested-With');
             header('Access-Control-Allow-Headers: Content-Type');
             header('Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT');
             header('Access-Control-Max-Age: 86400');
      }
  exit;
}
0
 

Author Comment

by:jacobs99
ID: 40620698
Radek, my bad.
For sure you are right that the problem was that dev02 was not cross domain enabled as you originally posted!
Thank you for your help!
Peter
0

Featured Post

Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Boost your ability to deliver ambitious and competitive web apps by choosing the right JavaScript framework to best suit your project’s needs.
Get to know the ins and outs of building a web-based ERP system for your enterprise. Development timeline, technology, and costs outlined.
This tutorial demonstrates how to identify and create boundary or building outlines in Google Maps. In this example, I outline the boundaries of an enclosed skatepark within a community park.  Login to your Google Account, then  Google for "Google M…
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

861 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question