1

I have simple API on Node.js with fake user data using Faker.js

var express = require('express'),
    app = express(),
    faker = require('faker');

app.set('port', process.env.PORT || 3500);

var router = new express.Router();

router.get('/api/user', function(req, res) {
    res.json({
        name: faker.name.findName(),
        email: faker.internet.email(),
        address: faker.address.streetAddress(),
        bio: faker.lorem.sentence(),
        image: faker.image.avatar()
    });
});

app.use('/', router);

var server = app.listen(app.get('port'), function() {
    console.log('Server up: http://localhost:' + app.get('port'));
});

it looks like this:

enter image description here

but when I'm trying to get this data using jQuery:

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script type="text/javascript" src="bower_components/jquery/dist/jquery.js"></script>
</head>
<body>
    <script type="text/javascript">
        $.getJSON('http://localhost:3500/api/user').done(function(data) {
            console.log(data)
        })
    </script>
</body>
</html>

I get the following error in the console:

XMLHttpRequest cannot load http://localhost:3500/api/user. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.

enter image description here

or with jQuery AJAX:

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script type="text/javascript" src="bower_components/jquery/dist/jquery.js"></script>
</head>
<body>
    <script type="text/javascript">
        $.ajax({
            url: "http://localhost:3500/api/user",
            jsonp: "callback",
            dataType: "jsonp",
            success: function(data) {
                console.log(data);
            }
        });
    </script>
</body>
</html>

enter image description here

Tell me please how to fix this problem and why it happens. How to get JSON data from my API ?

Edit:

The problem was that my API is on http://localhost:3500 and HTML with GET Request on http://localhost:8000 but CORS has not supported. I write answer for this question in which this problem is solved https://stackoverflow.com/a/36526208/6135469

Community
  • 1
  • 1
Axel
  • 109
  • 1
  • 1
  • 18
  • 1
    it means you need to modify the API application. Failing the same-origin policy due to different ports, the API must grant the other origin (port `8000`) permission to make the request. To do that, it must implement [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) by including appropriate `Access-Control-*` headers when it responds. (Also note [browser support](http://caniuse.com/#feat=cors) for CORS.) You can use the [`cors` module](https://www.npmjs.com/package/cors) to help with that. – Jonathan Lonowski Apr 10 '16 at 05:10
  • @JonathanLonowski Oh, many thanks. CORS Module solve my problem. – Axel Apr 10 '16 at 05:22
  • I've removed my comment that mentioned your IP. Though, without those comments for context, you should edit your question to note the other port/address being used for the HTML page. – Jonathan Lonowski Apr 10 '16 at 05:27

3 Answers3

4

Thanks for Jonathan Lonowski https://stackoverflow.com/users/15031/jonathan-lonowski

I solve my problem using CORS Module with Enable CORS for a Single Route

now code looks like this:

var express = require('express'),
    cors = require('cors'),
    app = express(),
    faker = require('faker');

app.set('port', process.env.PORT || 3500);

var router = new express.Router();

router.get('/api/user', cors(), function(req, res) {
    res.json({
        name: faker.name.findName(),
        email: faker.internet.email(),
        address: faker.address.streetAddress(),
        bio: faker.lorem.sentence(),
        image: faker.image.avatar()
    });
});

app.use('/', router);

var server = app.listen(app.get('port'), function() {
    console.log('Server up: http://localhost:' + app.get('port'));
});

and now I can get the data from the API with GET request from another port

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script type="text/javascript" src="bower_components/jquery/dist/jquery.js"></script>
</head>
<body>
    <script type="text/javascript">
        $.getJSON('http://localhost:3500/api/user').done(function(data) {
            console.log(data)
        })
    </script>
</body>
</html>
Community
  • 1
  • 1
Axel
  • 109
  • 1
  • 1
  • 18
  • 2
    you can set it for all the routes: `app.use(cors())` and put this before your first route starts. – Nivesh Apr 10 '16 at 06:54
1

You can also enable CORS without using the CORS Module

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();
});

Therefore, the code would look like this

var express = require('express'),
    app = express(),
    faker = require('faker');

app.set('port', process.env.PORT || 3500);

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();
});

app.get('/api/user', function(req, res) {
    res.json({
        name: faker.name.findName(),
        email: faker.internet.email(),
        address: faker.address.streetAddress(),
        bio: faker.lorem.sentence(),
        image: faker.image.avatar()
    });
});

var server = app.listen(app.get('port'), function() {
    console.log('Server up: http://localhost:' + app.get('port'));
});
Mikhail
  • 11,067
  • 7
  • 28
  • 53
-1

Change your $.ajax call to say 8000 if your app is on port 8000. Also you should change your environment variable PORT to 8000 or 3500 or change the code to that default so it is less confusing.

Jason Livesay
  • 6,317
  • 3
  • 25
  • 31