AngularJS + ServiceStack + Node.js as a proxxy? - angularjs

I have created an application in angularjs. The server side is covered by servicestack, I'd like to process a json file that is provided by the servicestack application. To do it I use following code in angularjs:
taskListApp.factory('Fact', function ($resource) {
return $resource("http://localhost:55267/hello?format=json", {},
{
query: {method: 'GET', url: "http://localhost:55267/hello?format=json"},
});
});
However I get the error in console about same origin policy, missing CORS header.
I'm trying to use the default node.js template to create a proxxy server, but I'm clueless about what ports should I use. Any headers?
EDIT:
this is my node.js code, which returns unhandled 'error' error
httpProxy.createServer({
target:'http://localhost:55267'
}).listen(8003);
http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2));
res.end();
}).listen(55267);

Not sure if this will resolve the issue with node but if you want to add CORS Response Headers to the ServiceStack response you need to register the CORS plugin in your AppHost's Configure():
Plugins.Add(new CorsFeature());

If you want to add CORS Response Headers to the ServiceStack response. Please add the below lines:
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");

Related

Cannot fetch from localhost with Authorization header

I'm having a hard time sending a get request to my expressjs backend with the fetch method.
fetch('http://localhost:9000', { method: 'GET', headers: { Authorization: `Bearer ${accessToken.accessToken}` }}).then(() => {
debugger
}).catch((error) => {
debugger
})
Based on what I could read, this seems correct - The request is however not reaching the API.
I tried constructing the options object like so, without any luck:
const options = {
method: "GET",
headers: headers
};
Without the headers, my request reaches the API. Anyway, the error that I'm getting is this:
error: TypeError: Failed to fetch
If you make that request from an origin other than http://localhost:9000, the Authorization header will cause the browser to make a CORS preflight request OPTIONS http://localhost:9000 before the GET request, and if that fails, the GET request would not be made.
You must ensure that your server handles the preflight, e.g., through the cors middleware.
So I found a solution, basically I added this middleware in my Express application to allow CORS,
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "*");
res.header("Access-Control-Allow-Methods", "*");
next();
});

How to send both data and header to a server?

I want to send a header to a server using http call POST request.
When I send the header only, everything is ok.
but when I add some data to the call, I get an error:
http://localhost:3000/test_post.
Request header field Content-Type is not
allowed by Access-Control-Allow-Headers in preflight response.
I use node.js as the server side language, this is the code for the CORS settings:
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Expose-Headers", "x-auth");
res.header("Access-Control-Allow-Headers", "x-auth");
next();
});
This is the $http call with angular:
$http({
method: 'POST',
data: {name: 'Dani'},
url: 'http://localhost:3000/test_post'
headers: {
'x-auth': 'some token'
}
}).then(function successCallback(response) {
console.log(response.data);
}, function errorCallback(response) {
console.log('error');
});
I know problem is about the CORS, but I don't know what to modify there,
If I remove res.header("Access-Control-Allow-Headers", "x-auth"); from the CORS I can get the data on the server but not the Header.
How can I get them both?
Hope you can help me with that, Thank you.

No 'Access-Control-Allow-Origin' header is present on the requested resource.

I've seen several questions and answers around this and mine is half working.
I have a node.js api server with url api.domain.com and the website on an nginx server at www.domain.com when I do the following in angular the request goes through on the api server, I see the request I see it getting parsed and put into the database. However, on the client side I do not get a return right away and then eventually I will see No 'Access-Control-Allow-Origin' header is present on the requested resource.
I know what is causing this behavior but shouldn't it throw the error before it hits the API server? Also note that the node.js server has cors enabled. The response that should be coming back is json.
$http({
method: 'POST',
url: "http://api.domain.com/addtrans/" + $scope.accountID,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS, PUT',
'Content-Type': 'application/x-www-form-urlencoded'
},
transformRequest: function (obj) {
var str = [];
for (var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
},
data: {
payload: JSON.stringify(trans)
}
}).success(function (result) {
$scope.trans = {};
console.log(result);
});
I have used the below middleware for all of our projects and it has been proven to work best.
const allowCors = (req, res, next) => {
/** Allow all origins, for now TODO */
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Headers', 'Authorization, Content-Type');
res.header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE');
/** Browser check for pre-flight request to determine whether the server is webdav compatible */
if ('OPTIONS' == req.method) {
res.sendStatus(204);
}
else next();
};
// Put this code before the routes you want to allow CORS to
app.use(allowCors);
You should change the Allow-Origin to something more restricted for security reasons.
The above code covers CORS as well as pre-flight on most browsers(this ia major issue we were having in the beginning).
i used this a while ago (express 3.x):
// npm install --save cors
var express = require('express');
var cors = require('cors');
var app = express();
app.use(cors());
app.use(express.static());
app.get('*', function(){});
require('http').createServer(app).listen(3000)
Remember that the cors header should be on the response which is coming from server not the request which is sent from client.
You can use a middleware to enable cors on the server:
//CORS middleware
var allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', 'example.com');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
}
//...
app.configure(function() {
...
app.use(allowCrossDomain);
...
});

CORS issue for Ionic + express

I have created an application that is accessing/fetching the data from mongo/node+express, which is on different domain(eg domain_name).
The code for the get function is :
var request = $http({
method: 'GET',
url: 'https://domain_name.users.io/categories/list',
withCredentials: true /* to get the Cookie value generated at server-side */
});
At the express side, have added the following code in order to avoid the CORS issue:
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods","GET,PUT,POST,DELETE,OPTIONS");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header("Access-Control-Allow-Credentials", "true");
For the above, i am getting the following error:
XMLHttpRequest cannot load https://domain_name.users.io/data/list. A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'http://localhost:8100' is therefore not allowed access.
I have checked the API "https://domain_name.users.io/data/list" and there is no issue with it as i can see the data(when hit on browser).
Could someone please help me for the same
Besides * is too permissive and would defeat use of credentials. So use https://domain_name.users.io/data/list rather than you use *.
You can't do like * because this is a part of security and if you want to allow credentials then your Access-Control-Allow-Origin must not use *.
For more please read here.
Must set the headers:
var request = $http({
method: 'GET',
url: 'https://domain_name.users.io/categories/list',
headers:{'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
withCredentials: true /* to get the Cookie value generated at server-side */
});
==============ON Node Side===============
app.use(function(req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type, Authorization, Access-Control-Allow-Origin, Access-Control-Allow-Headers');
next();
});

AngularJs $http GET passing custom header returns 404

I've been reading many blogs about it and I could not figure it out how to solve my problem..
I need to pass a token as a custom header to a get $http.. I get an error 404 because the GET request turns into OPTIONS.
The nodejs API Rest is working properly as I test it with the chrome "rest console" app.
Thank you Kasper..
This was my server code before starting this thread..
app.all('/*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", 'X-Requested-With, Content-Type');
res.header('Access-Control-Allow-Methods', 'GET, POST', 'DELETE', 'PUT');
next();
});
With this server code, everytime I send a request (GET) from the client with AngularJS adding a custom header "token"
myapp.factory("Booking", function ($resource) {
return $resource(
serverUrl + "/agp/pricelist",
{}, //default parameters
{
"reviews": {'method': 'GET', 'params': {'reviews_only': "true"}, isArray: true,
headers: {'Content-Type':'application/json', 'token': 'diego' }}
}
);
});
So, when you send a custom header rather than the followings:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type, but only if the value is one of:
application/x-www-form-urlencoded
multipart/form-data
text/plain
the type cors request is not "simple" anymore with a custom header, so when the client makes the request in fact it is making a pre-request with method "OPTIONS" first and then makes the "GET".. in between I was getting 404 error.
I added then to my server:
app.all('/*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", 'X-Requested-With, Content-Type, token');
res.header('Access-Control-Allow-Methods', 'GET, POST', 'DELETE', 'PUT', 'OPTIONS');
res.header('Access-Control-Request-Method', 'GET');
res.header('Access-Control-Request-Headers', 'token');
if ('OPTIONS' == req.method) {
res.send(200);
}
else {
next();
}
// next();
});
It was supposed to work with the access-control headers I added, but it was still sending back the 404 error.. So the work around was to add
if ('OPTIONS' == req.method) {
res.send(200);
}
else {
next();
}
Because as I said before, with a custom header the client first ask for permissions with OPTIONS method, and the sends the proper GET or whatever.
I did not find out another solution since this seems to be a work around, but at least I am not stuck anymore.
This is a good and practical link a about CORS
http://www.html5rocks.com/en/tutorials/cors/
Hope this helps someone.
King regards
I'm not too versed with CSRF and the likes, but I do believe this might be the issue I had with contacting my Express server with Angular.
http://mircozeiss.com/using-csrf-with-express-and-angular/
As stated in that article, Angular uses it's own X-XSRF-TOKEN for CSRF protection. Hence, you need to take that into account when setting up your server.
Following along with that guide and Express v3 all my requests going from the client side to the server side, magically started working.
If this is not the case (and I'm way out there), let me know.
What does your full serverside config look like?

Resources