6

I have a simple Node.js server up and running. This is the code:

var http = require('http');
var server = http.createServer();
server.on('request', function(req, res) {
    res.writeHead(200, {
        'content-type': 'text/plain'
    });
    res.write('Hello World!');
    res.end();
})

server.listen(8090);
server.once('listening', function() {
    console.log('Hello World server listening on port %d', 8090);
});

I can call this server using curl from the command line:

$curl localhost:8090

However, when I try to call it from a Vue application, I get an error. I have a Vue application running on localhost:8080, and I want to call my localhost:8090 server. My main.js Vue file is this:

import Vue from 'vue'
import resources from 'vue-resource'
Vue.use(resources)

import App from './components/App.vue'

import style from './styles/main.scss'

/**
 * Root Vue instance
 * @param {[element]} el: 'body' [Adds to the html body]
 * @param {[component]} components: {app: App} [Renders ./component/App]
 */
new Vue({
  el: 'body',
  components: {
    app: App
  }
})

And this is the App component:

<template>

<h1>{{ msg }}</h1>

<input v-model="msg">
<button v-on:click="get">Call Server</button>

</template>

<script>

export default {
    data: function() {
        return {
            msg: 'Hello World!'
        }
    },
    methods: {
        get: function() {
            // GET request
            this.$http({
                url: 'localhost:8090',
                method: 'GET'
            }).then(function(response) {
                console.log('ok');
            }, function(response) {
                console.log('failed');
            });
        }
    }
}

</script>

When I click the button I get this error:

XMLHttpRequest cannot load localhost:8090. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource.

When I try to call another server, like google.com, I get this error:

build.js:19188 GET http://localhost:8080/google.com 404 (Not Found)

So it seems like Vue is putting the localhost:8080 in front of the call, and maybe this is where my problem lies? Making server calls is completely new to me, I'm just playing around with Vue and want to learn Node.js while I do so.

2
  • Try to use full address like http:// www.google.com or http:// localhost:8090 Commented Apr 22, 2016 at 11:48
  • As @Molda says, you need to prefix your Google queries with the current protocol scheme, otherwise the browser will assume that your request is relative to the root of the server you are currently serving pages from. Commented Apr 23, 2016 at 6:29

2 Answers 2

6

This basically has nothing to do with Node or Vue and everything to do with how security in the browser is implemented. CORS is not a workaround. Read up on CORS to see why it is needed. This question of mine, which is quite similar to yours, has some good info in the answers sections as well. To be able to call an API without using CORS it needs to run on the same host, port and protocol, otherwise it will be blocked by your browser.

Years ago, before the advent of CORS, you needed to use JSONP to achieve the same. You can of course have a look at it to see how this works, but nowadays there is very little need for that technique as we have proper cross-domain support in the form of CORS.

Regarding your question in one of the comment sections on "How do people call API's when working with Vue.js?", they do one of the following:

  1. Run the API on another server (such as api.mydomain.com), but set the CORS headers on the response.
  2. As above, but the client and server wraps responses using the JSONP method mentioned above.
  3. Run the API on the same server as the one serving pages. This means api calls will be done against an endpoint such as localhost:8080/api
  4. Twist on #3: just proxy calls coming in on the server to another server. Meaning you can have your api server running elsewhere, but your main server that is accepting calls on /api will just send these requests on the the next server after stripping off the /api prefix. Usually, people either setup an Apache or Nginx instance in front of your app server and do the actual proxying on that, but you can also do it in your app server, using something like node-proxy.

You can probably read this through the lines already, but save yourself some trouble (and time) and just use CORS :) @trquoccuong has the details on doing this in his answer.

Sign up to request clarification or add additional context in comments.

1 Comment

This helped a lot!
3

CORS problems, you can use cors node module or add request header

if use Express

res.header('Access-Control-Allow-Origin', 'http://localhost:8080');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');

if use http module

res.setHeader

3 Comments

This gives me error: "XMLHttpRequest cannot load localhost:8090. The 'Access-Control-Allow-Origin' header has a value 'localhost:8080' that is not equal to the supplied origin. Origin 'localhost:8080' is therefore not allowed access."
Ok, this worked, but how can I access a server without this getaround? How do people call API's when working with Vue.js?
@ArashSaidi See my answer for an elaborate answer to your question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.