Jay
Jay

Reputation: 395

Angular 2 : Cross origin error

In angular 2 i get cross origin error. i am running project through ng serve using angular cli

not able to solve this issue as when i open XML file link in browser it opens perfectly but when i try to access the same in service it gives me error

// data service file

import { Injectable } from '@angular/core';
import { Http, Response, Headers } from '@angular/http';
import { Observable } from 'rxjs';
import 'rxjs/operator/map';
import 'rxjs/operator/catch';
import 'rxjs/observable/throw';
import { xml2js } from 'xml2js';

@Injectable()
export class DataService {
//parser = new xml2js.Parser({explicitArray : false});
  constructor(private http: Http) { }

  getLoginData(){
    return this.http.get('https://api.myjson.com/bins/zsjzj')
      .map((data:Response) => data.json())
      .catch(this.getError);
  } 

 /* getXML(){
    return this.http.get('http://www.xmlfiles.com/examples/note.xml')
                .flatMap(res=>{
                        return Observable.fromPromise(this.getJSON(res.text()))
                })
                .catch((error:any) => Observable.throw(error.json().error || 'Server error'));
  }*/
createAuthorizationHeader(headers:Headers) {
    headers.append('Authorization', 'Basic ' +
      btoa('a20e6aca-ee83-44bc-8033-b41f3078c2b6:c199f9c8-0548-4be7-9655-7ef7d7bf9d20')); 
  }

  xml2json(xml, tab) {
   var X = {
      toObj: function(xml) {
         var o = {};
         if (xml.nodeType==1) {   // element node ..
            if (xml.attributes.length)   // element with attributes  ..
               for (var i=0; i<xml.attributes.length; i++)
                  o["@"+xml.attributes[i].nodeName] = (xml.attributes[i].nodeValue||"").toString();
            if (xml.firstChild) { // element has child nodes ..
               var textChild=0, cdataChild=0, hasElementChild=false;
               for (var n=xml.firstChild; n; n=n.nextSibling) {
                  if (n.nodeType==1) hasElementChild = true;
                  else if (n.nodeType==3 && n.nodeValue.match(/[^ \f\n\r\t\v]/)) textChild++; // non-whitespace text
                  else if (n.nodeType==4) cdataChild++; // cdata section node
               }
               if (hasElementChild) {
                  if (textChild < 2 && cdataChild < 2) { // structured element with evtl. a single text or/and cdata node ..
                     X.removeWhite(xml);
                     for (var n=xml.firstChild; n; n=n.nextSibling) {
                        if (n.nodeType == 3)  // text node
                           o["#text"] = X.escape(n.nodeValue);
                        else if (n.nodeType == 4)  // cdata node
                           o["#cdata"] = X.escape(n.nodeValue);
                        else if (o[n.nodeName]) {  // multiple occurence of element ..
                           if (o[n.nodeName] instanceof Array)
                              o[n.nodeName][o[n.nodeName].length] = X.toObj(n);
                           else
                              o[n.nodeName] = [o[n.nodeName], X.toObj(n)];
                        }
                        else  // first occurence of element..
                           o[n.nodeName] = X.toObj(n);
                     }
                  }
                  else { // mixed content
                     if (!xml.attributes.length)
                        o = X.escape(X.innerXml(xml));
                     else
                        o["#text"] = X.escape(X.innerXml(xml));
                  }
               }
               else if (textChild) { // pure text
                  if (!xml.attributes.length)
                     o = X.escape(X.innerXml(xml));
                  else
                     o["#text"] = X.escape(X.innerXml(xml));
               }
               else if (cdataChild) { // cdata
                  if (cdataChild > 1)
                     o = X.escape(X.innerXml(xml));
                  else
                     for (var n=xml.firstChild; n; n=n.nextSibling)
                        o["#cdata"] = X.escape(n.nodeValue);
               }
            }
            if (!xml.attributes.length && !xml.firstChild) o = null;
         }
         else if (xml.nodeType==9) { // document.node
            o = X.toObj(xml.documentElement);
         }
         else
            alert("unhandled node type: " + xml.nodeType);
         return o;
      },
      toJson: function(o, name, ind) {
         var json = name ? ("\""+name+"\"") : "";
         if (o instanceof Array) {
            for (var i=0,n=o.length; i<n; i++)
               o[i] = X.toJson(o[i], "", ind+"\t");
            json += (name?":[":"[") + (o.length > 1 ? ("\n"+ind+"\t"+o.join(",\n"+ind+"\t")+"\n"+ind) : o.join("")) + "]";
         }
         else if (o == null)
            json += (name&&":") + "null";
         else if (typeof(o) == "object") {
            var arr = [];
            for (var m in o)
               arr[arr.length] = X.toJson(o[m], m, ind+"\t");
            json += (name?":{":"{") + (arr.length > 1 ? ("\n"+ind+"\t"+arr.join(",\n"+ind+"\t")+"\n"+ind) : arr.join("")) + "}";
         }
         else if (typeof(o) == "string")
            json += (name&&":") + "\"" + o.toString() + "\"";
         else
            json += (name&&":") + o.toString();
         return json;
      },
      innerXml: function(node) {
         var s = ""
         if ("innerHTML" in node)
            s = node.innerHTML;
         else {
            var asXml = function(n) {
               var s = "";
               if (n.nodeType == 1) {
                  s += "<" + n.nodeName;
                  for (var i=0; i<n.attributes.length;i++)
                     s += " " + n.attributes[i].nodeName + "=\"" + (n.attributes[i].nodeValue||"").toString() + "\"";
                  if (n.firstChild) {
                     s += ">";
                     for (var c=n.firstChild; c; c=c.nextSibling)
                        s += asXml(c);
                     s += "</"+n.nodeName+">";
                  }
                  else
                     s += "/>";
               }
               else if (n.nodeType == 3)
                  s += n.nodeValue;
               else if (n.nodeType == 4)
                  s += "<![CDATA[" + n.nodeValue + "]]>";
               return s;
            };
            for (var c=node.firstChild; c; c=c.nextSibling)
               s += asXml(c);
         }
         return s;
      },
      escape: function(txt) {
         return txt.replace(/[\\]/g, "\\\\")
                   .replace(/[\"]/g, '\\"')
                   .replace(/[\n]/g, '\\n')
                   .replace(/[\r]/g, '\\r');
      },
      removeWhite: function(e) {
         e.normalize();
         for (var n = e.firstChild; n; ) {
            if (n.nodeType == 3) {  // text node
               if (!n.nodeValue.match(/[^ \f\n\r\t\v]/)) { // pure whitespace text node
                  var nxt = n.nextSibling;
                  e.removeChild(n);
                  n = nxt;
               }
               else
                  n = n.nextSibling;
            }
            else if (n.nodeType == 1) {  // element node
               X.removeWhite(n);
               n = n.nextSibling;
            }
            else                      // any other node
               n = n.nextSibling;
         }
         return e;
      }
   };
   if (xml.nodeType == 9) // document node
      xml = xml.documentElement;
   var json = X.toJson(X.toObj(X.removeWhite(xml)), xml.nodeName, "\t");
   return "{\n" + tab + (tab ? json.replace(/\t/g, tab) : json.replace(/\t|\n/g, "")) + "\n}";
}

getCompanies() {
  	var headers = new Headers();
  	this.createAuthorizationHeader(headers);
  	headers.append('Accept', 'application/xml');

  	return this.http.get('https://angular2.apispark.net/v1/companies/', {
      headers: headers
    }).map(res => JSON.parse(this.xml2json(res.text(),'  ')));
  }

  private getError(error: Response):Observable<String>{
      return Observable.throw(error.json() || 'Server Issue');
  }


}
//error

OPTIONS http://172.21.103.105:15871/cgi-bin/blockpage.cgi?ws-session=2053590089 404 (Not Found)
:4200/login:1 XMLHttpRequest cannot load http://172.21.103.105:15871/cgi-bin/blockpage.cgi?ws-session=2053590089. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. The response had HTTP status code 404.
core.es5.js:1085 ERROR Response {_body: ProgressEvent, status: 0, ok: false, statusText: "", headers: Headers…}
defaultErrorLogger @ core.es5.js:1085
ErrorHandler.handleError @ core.es5.js:1145
next @ core.es5.js:4774
schedulerFn @ core.es5.js:3848
SafeSubscriber.__tryOrUnsub @ Subscriber.js:234
SafeSubscriber.next @ Subscriber.js:183
Subscriber._next @ Subscriber.js:125
Subscriber.next @ Subscriber.js:89
Subject.next @ Subject.js:55
EventEmitter.emit @ core.es5.js:3834
NgZone.triggerError @ core.es5.js:4205
onHandleError @ core.es5.js:4166
webpackJsonp.579.ZoneDelegate.handleError @ zone.js:369
webpackJsonp.579.Zone.runTask @ zone.js:168
ZoneTask.invoke @ zone.js:460

Upvotes: 0

Views: 2179

Answers (2)

VikingCode
VikingCode

Reputation: 1052

Intro to your problem

The Access-Control-Allow-Origin is a part of CORS (Cross-Origin Resource Sharing) mechanism that gives web servers cross-domain access controls. It is in place to protect your app/site from CSRF (Cross-Site Request Forgery).

Ow and it's enforced by the browser

CORS / CSRF

The problem

Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. The response had HTTP status code 404.

Your backend (172.21.103.105:15871) is saying: You cannot fetch data from other domains.

To fix this problem you have to edit your backend webserver configuration to allow your frontend app to query data from your backend (same ip different port === different domain)

What are you using as backend web server? If you provide it I'll edit my post with steps to follow. But you can google it very easily.

Upvotes: 1

Fredrik Lundin Grande
Fredrik Lundin Grande

Reputation: 8186

Since you are using the Angular CLI (which is using webpack under the hood), you can proxy your front-end app to the back-end. This will "trick" (proxy, actually) to the back-end to think your front-end request is coming from the same domain.

This solution is good if the server URL you are trying to access only allows requests from the same domain it is on, and your application is going to run on the same domain.

Meaning - if when you have your application deployed in production it will be hosted on the same domain as service you are calling - this is a good approach. If the service is a third party service that will not be hosted on the same domain as your application, then you will receive a CORS error from your hosted application anyway.

You setup the proxy by creating a proxy config file containing something like this:

{
  "/api": {
    "target": "_your_backend_ip_",
    "secure": false
  }
}

Then serve your application with a npm script like this:

"start": "ng serve --proxy-config _your_proxy_config_.json"

Have a look at the documentation HERE

Upvotes: 1

Related Questions