Apache and Nodejs cross domain ajax issue - ajax

I am working on application in which I have used two servers hosted on same machine, one is apache which will work as basic host for serving php pages and other side nodejs for communication of rest api, whole application build upon backbone/marionette/requirejs/bootstrap.
Coming to the point, my normal pages are load from apache server like,
http://192.168.20.62/project/design.php
and I have configured my model like this,
define(['backbone'],function(Backbone){
'use strict';
return Backbone.Model.extend({
url:"http://192.168.20.62:9847/page",
defaults: {
...
}
});
});
when I try to save model I am suffering from problem of ajax cross domain call and I am ended up with error in my save communication, following is the node/express server,
var express = require('/root/node_modules/express');
var app = express();
app.configure(function () {
app.use(express.json());
app.use(express.urlencoded());
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', 'http://192.168.20.62:9847');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
})
app.post('/page', function(request, response){
console.log(request.body);
response.send(request.body);
});
app.listen(9847);
as you can see I have already written some patch in server code, but still the same, also I have added .htaccess at root level of both at
http://192.168.20.62
and
http://192.168.20.62:9847
with the following code,
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"
but things are not helping in anyways, if I run chrome by disabling web security then thing are working properly.
chrome.exe --disable-web-security
Can you guys please help me to solve this puzzle, thanks in advance.
following is the error message from chrome javascript console
OPTIONS http://192.168.20.62:9847/page Origin http://192.168.20.62 is not allowed by Access-Control-Allow-Origin. jquery-2.0.3.min.js:6
XMLHttpRequest cannot load http://192.168.20.62:9847/page. Origin http://192.168.20.62 is not allowed by Access-Control-Allow-Origin.

Oops I figure out the problem, I have setup wrong url for white listing.
res.setHeader('Access-Control-Allow-Origin', 'http://192.168.20.62');
I have to whitelist the source URL which was generating cross domain, this was the only change have to do to make thing running.
Also this has browser version impact, when I have posted this issue, I was checking with firefox version 24.0.* and when I upgrade 25.0 it has stopped generating cross domain error surprisingly. But still Chrome giving natural cross domain error, when I read error message of chrome carefully I come to know that I have whitelisted wrong url.
XMLHttpRequest cannot load http://192.168.20.62:9847/page. The 'Access-Control-Allow-Origin' whitelists only 'http://192.168.20.62:9847'. Origin 'http://192.168.20.62' is not in the list, and is therefore not allowed access.

If you don't have to deal with WebSockets, then place Node.js behind Apache via mod_proxy:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule rewrite_module modules/mod_rewrite.so
# disable use as forward proxy
ProxyRequests Off
# don't handle Via: headers - we don't care about them
ProxyVia Off
# no need to transport host name - not doing virtual hosting
ProxyPreserveHost Off
ProxyPass /page/ http://192.168.20.62:9847/page/
ProxyPassReverse /page/ http://192.168.20.62:9847/page/
# If you get HTTP status code 502 (Bad Gateway), maybe this could help
SetEnv force-proxy-request-1.0 1
SetEnv proxy-nokeepalive 1
In your web-page you can access your API with the same port as your Apache and you don't have any problems with Cross-Domain / Same-Origin-Policy.
You just have to separate your URIs now, e.g /page/ exists only in node.js app.
If you're serving REST only (no HTML/CSS/Images) via node.js, using JSONP would be another option. Here is a good+short description how to handle JSONP in Express

Related

enable jquery load cross domain with a proxy

I have two resources. A standard apache website on mycooldomain.com and a node website on mycooldomain.com:4337. On the apache vhost I have defined a proxy so that i can reach node using mycooldomain.com/myapp.
Now what I am trying to do is to have this code working in mycooldomain.com/index.html:
$('#somediv').load('/myapp');
but this will end with the browser blocking the request marking it as "insecure".
I assume that the proxy should be the workaround to put the two requests on the same domain but as far as I can see I am missing something.
My proxy definition in apache is the following:
ProxyPreserveHost On
SSLProxyEngine On
ProxyPass /myapp https://mycooldomain.com:4337
ProxyPassReverse /myapp https://mycooldomain.com:4337
What am I missing?
I also tried to add to this:
Header always add Strict-Transpor-Security "max-age=15552000; include subdomains"
the following line:
Header set Access-Control-Allow-Origin "https://mycooldomain.com:4337"
but this didn't solve the issue either.
Any hint?

"Not allowed to request resource" in Safari and "Blocked loading mixed active content" in Firefox. Perfect functionality in Chrome

I am working on an app using a React frontend and Express backend, with GraphQL setup through Apollo (I am following and modifying tutorial https://www.youtube.com/playlist?list=PLN3n1USn4xlkdRlq3VZ1sT6SGW0-yajjL)
I am currently attempting deployment, and am doing so with Heroku. Everything functions perfectly on my local machine before deployment and on Heroku in Google Chrome. However, I get the aforementioned errors in Safari and Firefox, respectively. Wondering why this is happening in these browsers and how to fix.
I have spent about 10 hrs doing research on this. Things I tried that made no difference:
I tried adding CORS to my express backend
I tried serving the graphql endpoint as HTTPS
Moving app.use(express.static) in main app.js server file
I couldn't find many other things to try. Everywhere I looked seemed to say that CORS fixed the problem, but mine persists.
Github link: https://github.com/LucaProvencal/thedrumroom
Live Heroku App: https://powerful-shore-83650.herokuapp.com/
App.js (express backend):
const cors = require('cors')
// const fs = require('fs')
// const https = require('https')
// const http = require('http')
app.use(express.static(path.join(__dirname, 'client/build')));
app.use(cors('*')); //NEXT TRY app.use(cors('/login')) etc...
app.use(cors('/*'));
app.use(cors('/'));
app.use(cors('/register'));
app.use(cors('/login'));
app.get('/login', (req, res) => {
res.sendFile(path.join(__dirname, "client", "build", "index.html"));
});
app.get('/register', (req, res) => {
res.sendFile(path.join(__dirname, "client", "build", "index.html"));
});
server.applyMiddleware({ app }); // app is from the existing express app. allows apollo server to run on same listen command as app
const portVar = (process.env.PORT || 3001) // portVar cuz idk if it will screw with down low here im tired of dis
models.sequelize.sync(/*{ force: true }*/).then(() => { // syncs sequelize models to postgres, then since async call starts the server after
app.listen({ port: portVar }, () =>
console.log(`🚀 ApolloServer ready at http://localhost:3001${server.graphqlPath}`)
)
app.on('error', onError);
app.on('listening', onListening);
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
Full file is on Github, I tried to post only relevant parts above.
The expected result is that it works in all browsers. It seems from my research that since Heroku serves on HTTPS, Safari and Firefox do not allow requests to HTTP (which is where the graphql server is located, http://localhost:3001/graphql'). When I tried serving Apollo on HTTPS, Heroku just crashed, giving me H13 and 503 errors.
Thanks for any help...
This may also happen during local development when running the front end using HTTPS, but the back end using HTTP.
This is because CORS treats two URLs as having the same origin "only when the scheme, host, and port all match". Matching scheme means matching protocols e.g. both http, or both https.
One solution for local development is to proxy the back end using a tool such as ngrok.
Suppose the front end uses an environment variable which indicates the back end's URL:
BACK_END_API_URL=http://localhost:3005. Then do the following.
Install ngrok
Identify what port the back end is running on e.g. 3005
Run ngrok http 3005 at the command line, which will establish both http and https endpoints. Both will ultimately proxy the requests to the same back end endpoint: http://localhost:3005
After running ngrok it will display the http and https endpoints you can use. Put the one that matches the front end protocol you're using (e.g. https) into your front end environment variable that indicates the back end's URL e.g.
BACK_END_API_URL=https://1234asdf5678ghjk.ngrok.io
Was going to delete this because it is such a silly problem but maybe it will help someone in the future:
I simply replaced all of my 'http://localhost:PORT' endpoints in development with '/graphql'. I assumed that localhost meant local the machine running the code. But an app running on Heroku does not point to localhost. The express server is served on the url (https://powerful-shore-83650.herokuapp.com/) in our case...
At any rate I am so glad I came to a solution. I have a full stack app deployed and connected to a db. Hopefully this post can save someone lots of time.

Getting CORS blocked even after ("Access-Control-Allow-Origin", "*")

I am getting CORS blocked regardless of what I allow. It only yells at me for my POST route, my GET routes it allows just fine. I consistently get
Access to XMLHttpRequest at 'https://simple-startup-survey-backend.herokuapp.com/client_answers' from origin 'http://simple-startup-survey.surge.sh' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I am using an AJAX to communicate with an EXPRESS server. I allow all requests with the wildcard operator. I have tried sending {crossDomain: true} with my request.
//This is my backend in app.js
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET,POST,DELETE,PATCH,PUT");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
// This is my front end AXIOS call POST request. This is what is //triggering the CORS block
storedData = storedData.concat(storedData2)
axios.post('https://simple-startup-survey-backend.herokuapp.com/client_answers', {crossDomain:true}, storedData,)
.then(function(response){
console.log(response.data , ' save success')
localStorage.setItem("storedData", JSON.stringify(storedData))
window.location.href = "../AnalysisPage/analysis.html";
}).catch()
})
// This is my perfectly functional GET request. It does a bunch of //stuff after this in the .then, but I don't think that is relevant to //this issue
function getgeneralQuestions(){
axios.get('https://simple-startup-survey-backend.herokuapp.com/questions/balanceSheet')
.then(function (response) {
Every damn Google search result on the planet says that what I have in regards to my back end should work. I am using vanilla JS, no JQUERY.
Any help greatly appreciated!
back end Github: https://github.com/TuckerNemcek/SimpleSurveyBackend
front end Github: https://github.com/TuckerNemcek/SimpleStartupSurveyProject
I am running into a similar issue.
My hunch is that surge.sh does not have cors enabled on its server.
My website is actually making the request correctly.
Afterward there is an error and the data is not shown.
Edit: Solved - - - -
Actually, just solved this for myself!
This is my script for publishing.
yarn build; cp build/index.html build/200.html; echo '*' > build/CORS; surge build appname.surge.sh
here is an article about enabling cors for surge.sh https://github.com/surge-sh/example-cors
Also when making changes make sure you are in a new incognito tab each time or go to the network tab on dev tools and Disable cache otherwise your app might be lying to you and thing cors is not enabled when it in fact is enabled.

How to fetch RSS feed data in angular2 [duplicate]

I'm making an Ajax.request to a remote PHP server in a Sencha Touch 2 application (wrapped in PhoneGap).
The response from the server is the following:
XMLHttpRequest cannot load http://nqatalog.negroesquisso.pt/login.php. Origin http://localhost:8888 is not allowed by Access-Control-Allow-Origin.
How can I fix this problem?
I wrote an article on this issue a while back, Cross Domain AJAX.
The easiest way to handle this if you have control of the responding server is to add a response header for:
Access-Control-Allow-Origin: *
This will allow cross-domain Ajax. In PHP, you'll want to modify the response like so:
<?php header('Access-Control-Allow-Origin: *'); ?>
You can just put the Header set Access-Control-Allow-Origin * setting in the Apache configuration or htaccess file.
It should be noted that this effectively disables CORS protection, which very likely exposes your users to attack. If you don't know that you specifically need to use a wildcard, you should not use it, and instead you should whitelist your specific domain:
<?php header('Access-Control-Allow-Origin: http://example.com') ?>
If you don't have control of the server, you can simply add this argument to your Chrome launcher: --disable-web-security.
Note that I wouldn't use this for normal "web surfing". For reference, see this post: Disable same origin policy in Chrome.
One you use Phonegap to actually build the application and load it onto the device, this won't be an issue.
If you're using Apache just add:
<ifModule mod_headers.c>
Header set Access-Control-Allow-Origin: *
</ifModule>
in your configuration. This will cause all responses from your webserver to be accessible from any other site on the internet. If you intend to only allow services on your host to be used by a specific server you can replace the * with the URL of the originating server:
Header set Access-Control-Allow-Origin: http://my.origin.host
If you have an ASP.NET / ASP.NET MVC application, you can include this header via the Web.config file:
<system.webServer>
...
<httpProtocol>
<customHeaders>
<!-- Enable Cross Domain AJAX calls -->
<remove name="Access-Control-Allow-Origin" />
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
</system.webServer>
This was the first question/answer that popped up for me when trying to solve the same problem using ASP.NET MVC as the source of my data. I realize this doesn't solve the PHP question, but it is related enough to be valuable.
I am using ASP.NET MVC. The blog post from Greg Brant worked for me. Ultimately, you create an attribute, [HttpHeaderAttribute("Access-Control-Allow-Origin", "*")], that you are able to add to controller actions.
For example:
public class HttpHeaderAttribute : ActionFilterAttribute
{
public string Name { get; set; }
public string Value { get; set; }
public HttpHeaderAttribute(string name, string value)
{
Name = name;
Value = value;
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
filterContext.HttpContext.Response.AppendHeader(Name, Value);
base.OnResultExecuted(filterContext);
}
}
And then using it with:
[HttpHeaderAttribute("Access-Control-Allow-Origin", "*")]
public ActionResult MyVeryAvailableAction(string id)
{
return Json( "Some public result" );
}
As Matt Mombrea is correct for the server side, you might run into another problem which is whitelisting rejection.
You have to configure your phonegap.plist. (I am using a old version of phonegap)
For cordova, there might be some changes in the naming and directory. But the steps should be mostly the same.
First select Supporting files > PhoneGap.plist
then under "ExternalHosts"
Add a entry, with a value of perhaps "http://nqatalog.negroesquisso.pt"
I am using * for debugging purposes only.
This might be handy for anyone who needs to an exception for both 'www' and 'non-www' versions of a referrer:
$referrer = $_SERVER['HTTP_REFERER'];
$parts = parse_url($referrer);
$domain = $parts['host'];
if($domain == 'google.com')
{
header('Access-Control-Allow-Origin: http://google.com');
}
else if($domain == 'www.google.com')
{
header('Access-Control-Allow-Origin: http://www.google.com');
}
If you're writing a Chrome Extension and get this error, then be sure you have added the API's base URL to your manifest.json's permissions block, example:
"permissions": [
"https://itunes.apple.com/"
]
I will give you a simple solution for this one. In my case I don't have access to a server. In that case you can change the security policy in your Google Chrome browser to allow Access-Control-Allow-Origin. This is very simple:
Create a Chrome browser shortcut
Right click short cut icon -> Properties -> Shortcut -> Target
Simple paste in "C:\Program Files\Google\Chrome\Application\chrome.exe" --allow-file-access-from-files --disable-web-security.
The location may differ. Now open Chrome by clicking on that shortcut.
I've run into this a few times when working with various APIs. Often a quick fix is to add "&callback=?" to the end of a string. Sometimes the ampersand has to be a character code, and sometimes a "?": "?callback=?" (see Forecast.io API Usage with jQuery)
This is because of same-origin policy. See more at Mozilla Developer Network or Wikipedia.
Basically, in your example, you to need load the http://nqatalog.negroesquisso.pt/login.php page only from nqatalog.negroesquisso.pt, not localhost.
if you're under apache, just add an .htaccess file to your directory with this content:
Header set Access-Control-Allow-Origin: *
Header set Access-Control-Allow-Headers: content-type
Header set Access-Control-Allow-Methods: *
In Ruby on Rails, you can do in a controller:
headers['Access-Control-Allow-Origin'] = '*'
If you get this in Angular.js, then make sure you escape your port number like this:
var Project = $resource(
'http://localhost\\:5648/api/...', {'a':'b'}, {
update: { method: 'PUT' }
}
);
See here for more info on it.
You may make it work without modifiying the server by making the broswer including the header Access-Control-Allow-Origin: * in the HTTP OPTIONS' responses.
In Chrome, use this extension. If you are on Mozilla check this answer.
We also have same problem with phonegap application tested in chrome.
One windows machine we use below batch file everyday before Opening Chrome.
Remember before running this you need to clean all instance of chrome from task manager or you can select chrome to not to run in background.
BATCH: (use cmd)
cd D:\Program Files (x86)\Google\Chrome\Application\chrome.exe --disable-web-security
In Ruby Sinatra
response['Access-Control-Allow-Origin'] = '*'
for everyone or
response['Access-Control-Allow-Origin'] = 'http://yourdomain.name'
When you receive the request you can
var origin = (req.headers.origin || "*");
than when you have to response go with something like that:
res.writeHead(
206,
{
'Access-Control-Allow-Credentials': true,
'Access-Control-Allow-Origin': origin,
}
);

How to enable CORS on Sonatype Nexus?

I want to develop a Monitoring-WebApp for different things with AngularJS as Frontend. One of the core-elements is showing an overview of Nexus-Artifacts/Repositories.
When I request the REST-API I'm getting following error back:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://localhost:9090' is therefore not allowed access.
To fix this error, I need to modify the response headers to enable CORS.
It would be great if anyone is familiar with that type of problem and could give me an answer!
The CORS headers are present in the response of the system you are trying to invoke. (Those are checked on the client side [aka browser this case], you can implement a call on your backend to have those calls and there you can ignore those headers, but that could become quite hard to maintain.) To change those you'll need a proxy. So your application will not call the url directly like
fetch("http://localhost:9090/api/sometest")
There are at least two ways: one to add a proxy directly before the sonar server and modify the headers for everyone. I do not really recommend this because of security reasons. :)
The other more maintaneable solution is to go through the local domain of the monitoring web app as follows:
fetch("/proxy/nexus/api/sometest")
To achieve this you need to setup a proxy where your application is running. This could map the different services which you depend on, and modify the headers if necessary.
I do not know which application http server are you going to use, but here are some proxy configuration documentations on the topic:
For Apache HTTPD mod_proxy you could use a configuration similar to this:
ProxyPass "/proxy/nexus/" "http://localhost:9090/"
ProxyPassReverse "/proxy/nexus/" "http://localhost:9090/"
It is maybe necessary to use the cookies as well so you may need to take a look at the following configurations:
ProxyPassReverseCookiePath
ProxyPassReverseCookieDomain
For Nginx location you could employ something as follows
location /proxy/nexus/ {
proxy_pass http://localhost:9090/;
}
For node.js see documentation: https://github.com/nodejitsu/node-http-proxy
module.exports = (req, res, next) => {
proxy.web(req, res, {
target: 'http://localhost:4003/',
buffer: streamify(req.rawBody)
}, next);
};

Resources