Reputation: 395
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
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
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
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