Backend API call works internally (localhost) but fails externally (app.vueApp.com)

Hi,

I am new to VueJS development and I’m stuck with VueJS deployment from past few days. The VueApp works perfectly internally (localhost). The main point to address is there is no proxy setting used to communicate with the backend. As suggested in this post using custom instance of axios https://forum.vuejs.org/t/api-proxying-and-axios/27966/5?u=vuebeginner which is setup in my project within file axios.js. This means there is no proxy setting in vue.config.js.

The axios.js configuration which is configured can be seen below:

"use strict";

import Vue from 'vue';
import axios from "axios";

// Full config:  https://github.com/axios/axios#request-config
// axios.defaults.baseURL = process.env.baseURL || process.env.apiUrl || '';
// axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
// axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

let config = {
  baseURL: process.env.VUE_APP_API_URL
  // timeout: 60 * 1000, // Timeout
  // withCredentials: true, // Check cross-site Access-Control
};

const _axios = axios.create(config);

_axios.interceptors.request.use(
  function(config) {
    // Do something before request is sent
    return config;
  },
  function(error) {
    // Do something with request error
    return Promise.reject(error);
  }
);

// Add a response interceptor
_axios.interceptors.response.use(
  function(response) {
    // Do something with response data
    return response;
  },
  function(error) {
    // Do something with response error
    return Promise.reject(error);
  }
);

Plugin.install = function(Vue) {
  Vue.axios = _axios;
  window.axios = _axios;
  Object.defineProperties(Vue.prototype, {
    axios: {
      get() {
        return _axios;
      }
    },
    $axios: {
      get() {
        return _axios;
      }
    },
  });
};

Vue.use(Plugin)

export default Plugin;

API_URL: is my server side URL with port 10100 eg. XX.XX.XX.XX:10100

Note: The host is my IP Address, which i have mentioned with XXX.XXX.XX.XX for reference.

So any function call from VueApp to backend would be like:

            loginUser(id){
                this.loggingIn = true;
                this.$axios
                    .post("/user/login",{
                        userId: id
                    })
                    .then(response => {

and vue.config.js configuration is seen below:

module.exports = {
  //...
  devServer: {
    host: "XX.XX.XX.XXX",
    disableHostCheck: true,
    port: 8080,
    watchOptions: {
      watch: true,
      poll: true
    }
    // proxy:{
    //   '^/users':{
    //     target: 'http://XX.XX.XX.XX:10100',
    //     changeOrigin: true
    //     // loglevel: 'debug',
    //     // pathRewrite:{"^/users": "/"}
    //   }
    // }
  }
 // publicPath: "/"
};

Note I dont have any problem with the app running in locally. But now when I want it to be deployed or accessed externally only the VueApp (Frontend) gets rendered but backend call fails with CONNECTION_TIMED_OUT error. Please let me know how do i resolve this.

Thanks in advance :slight_smile:

Hey there, welcome to Vue and to the community!

Where are you deploying and running your frontend externally? A web host somewhere (e.g. cPanel)?

Is your “non-dev” backend behind a different baseUrl? Is your .env reflecting this when you do a production build?

Is the timeout error occurring when accessing from a different machine than your own?

From what I understand (with some assumptions):
Locally (working):
Vue: http://localhost:8080
Backend :http://xx.xx.xx.xx:10100 (running on same machine as vue frontend?)

When running locally, what do the network calls in dev tools show when you make an api call? Is it proxying from 8080:10100?

Externally (getting timeout):
Vue: http://a-real-website.com
Backend: ??? ← What is the URI for this?

Keep in mind that the proxy only runs when using the dev server locally.

1 Like

Hi @vanpyrzericj thanks for your quick response :slight_smile:

Please find the answers to your questions below:

Where are you deploying and running your frontend externally? A web host somewhere (e.g. cPanel)?

A: The App is running locally, . We have a support team who sets a proxy registry to my running App. To be more clear I just had to give my target machine where the App is running (which is locally) i.e http://XX.XX.XX.XX:8080 ===>http://app.webApp.com (he created a new domain). Note the URL is just an example

Is your “non-dev” backend behind a different baseUrl? Is your .env reflecting this when you do a production build?

A: Please find my .env configuration for your question

VUE_APP_TITLE = WebApp
VUE_APP_BASE_URL = http://XX.XX.XX.XX:8080
VUE_APP_API_URL = http://XX.XX.XX.XX:10100
NODE_ENV=development

The API_URL is my actual backend server.

Is the timeout error occurring when accessing from a different machine than your own?

A: Basically the App is running in a VM in a intra-organization network. It works fine inside the intra-org setup. But when i access it outside the organization i.e (inter-organization) with URL: http://app.webApp.com, I get the frontend (VUE_APP_BASE_URL) loaded but not the backend (VUE_APP_API_URL), this results in TIMEOUT_ERROR

When running locally, what do the network calls in dev tools show when you make an api call? Is it proxying from 8080:10100?

A: An example of a API call is seen below with details and logs:

The initial page will load list of users, with API Call GET: /users(this gets triggered on load of the main dashboard in frontend)

Logs: (When i am in intra Org network) (Works fine)
{“GET”:{“scheme”:“http”,“host”:“XX.XX.XX.XX:10100”,“filename”:"/users/",“remote”:{“Address”:“XX.XX.XX.XX:10100”}}}

Request Headers:

HTTP/1.1 304 Not Modified
X-Powered-By: Express
Access-Control-Allow-Origin: *
...

Response Headers:

GET /users/ HTTP/1.1
Host: XX.XX.XX:10100
User-Agent: Mozilla/5.0 (X11; Linux x86_64;) Gecko/20100101 Firefox/80.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Origin: http://app.WebApp.com
Connection: keep-alive
Referer: http://app.webApp.com/login

Logs: (When i am accessing App outside my Organization network) (Does not work )

Request Headers:

Referer: http://app.webApp.com/
User-Agent: Mozilla/5.0 (X11; Linux x86_64;) Gecko/20100101 Firefox/80.0
Accept: application/json, text/plain, */*
...

In General block:

Request URL: http://XX.XX.XX.XX:10100
Referrer policy: strict-origin-when-cross-origin

Backend: ??? ← What is the URI for this?
A: As pointed above the URI is: http://XX.XX.XX.XX:10100

On the contrary i just tried setting up this project mentioned in medium ( https://medium.com/bb-tutorials-and-thoughts/vue-js-how-to-proxy-to-backend-server-a562bad965eb) externally and it works fine. I am confused is it the way I am requesting backend call through axios?

I think the issue here is that Vue runs entirely client-side. So as shown, your GET request initiated by Vue requests an internal IP for your backend server xx.xx:10100 (where xx.xxx = the same machine running Vue on 8080). This is fine on-network, because xx.xx is available internally.

But, the moment you’re external/off-network, it can’t resolve xx.xx:10100 since that’s a LAN IP, which is what you’re telling it to try to connect to via VUE_APP_API_URL.

Let me guess, does xx.xxx of the format 10.x.x.x?

tldr; Here’s what you should try:
Have your network team setup a second domain (for example http://api.app.webApp.com) which connects to xx.xx:10100. Then change that VUE_APP_API_URL value to that new backend/api domain created.

I’ll bet that’ll solve this, since I assume when they setup that domain proxy, it essentially enables off-network traffic to connect to on-network machines.

1 Like

I am not sure about having a different domain for the backend. Nevertheless will give a try. However my main point would be as I told earlier, I tried setting up another dummy project as mentioned in this medium ( Vue.js — How To Proxy To Backend Server | by Bhargav Bachina | Bachina Labs | Medium) which externally works fine. I am confused is it the way I am requesting backend call through axios?

However when i was investigating on the other side, it seems I am facing the similar issue as mentioned in the link:

But based on my logs i see web socket error when accessing from external IP. Thanks :slight_smile:

So just to be clear, the dummy project you created from the Medium.com tutorial has an identical setup as far as your devServer.proxy object goes? Both the dummy project and your real one are pointing to the same proxy target (backend server)? And the dummy project was running on your app.webApp.com domain on that same VM that the broken project is?

I guess I’m trying to understand the delta between the dummy project and the real (but broken) one.

The error mentioned in that other link is essentially because of how npm run serve only uses http instead of https. Is your target backend server for the proxy exposed on http or https protocol? Its possible that is the source of your timeout.

I’ve never personally used the Vue devServer proxy feature, but I’d imagine it logs to the console when its running - so try making a backend call (which would timeout) and see if the console spits out anything useful. If you’re seeing that same ERR_SSL_PROTOCOL message in that contexts (which it sounds like you are), then my guess is that its mismatching somewhere - likely trying to connect to your backend via https while the backend only supports http (or vice versa) which is causing the timeout. Depending on what type of backend server you have, many have a separate port for http vs https. For example, asp.net core will by default serve http://localhost:5000 and https://localhost:5001

1 Like

Based on your reply, here is my response

The project which I created does not have identical setup as with the medium project. As mentioned earlier I am avoiding proxy based on axios instance as posted in this link API Proxying and axios - #5 by Khyme in my actual project. In case of the medium project it uses proxy setting as mentioned in the medium blog. I tried giving both the projects (app.WebApp.com & medium one) to the support team to host. The medium project was hosted with app.WebApp2.com. Any how the medium project worked interacting with the backend successfully. Note the backend server is exposed on http protocol. I tried checking the console when invoking backend and I am not seeing any ERR_SSL_PROTOCOL error
So based on the above inference, I see that the way I am interacting with the backend might be the reason. Still not clear, so minute but so big … :face_with_monocle:

Any chance you are comfortable with privately sending me the two web app URLs for me to check out on my end? I agree that the interaction is the culprit, however without a more direct insight, I’m not sure how much more I personally could help.

@JamesThomson may be a good fresh pair of eyes on this thread. I may have gone down the wrong rabbit hole at this point, and would rather a pro take their stab at this, too.

1 Like

The first thing you should test and confirm is whether you can access your deployed backend (non intra-net) through another means, e.g. Postman. If you’re able to make requests through Postman just fine, then you likely have a config issue somewhere on your frontend server. If you can’t, well, then it’s your backend that has the issue. This should at least help you narrow your focus.

1 Like

@vanpyrzericj Really appreciate your support. I can share you the details privately.

@JamesThomson Thanks for the support :slight_smile: I already tried testing the same with Postman. I am not able to make backend calls when I am in non intranet. When I am in my intranet I can make my backend calls and it works without timeout error.

True, based on this test i narrowed down and came to conclusion that its the backend call which is causing the problem as I stated in the initial problem info. I just got lead based on the node-proxy and working on the same to see if this solves the issue.
Here is the link for the same: GitHub - chimurai/http-proxy-middleware: The one-liner node.js http-proxy middleware for connect, express and browser-sync. Not sure if I am going in the right direction, nevertheless will update here if this works.

Sorry, I took some time to reply here. The issue remains still unsolved.
@JamesThomson I tried using http-nodejs-proxy but couldn’t resolve it. I can share you the link privately but I don’t know how I share it privately here? Any hint to move on is very much appreciated.

Thanks in advance :slight_smile:

I won’t claim to be an expert on proxies, but as I understand them, this is not the solution to your problem. If you cannot access the intranet from an external source a proxy will not help you. The intranet first needs to be setup to allow external connections in (otherwise what’s the point of firewalls, etc. if you could just setup a proxy to bypass them).

A proxy is intended to be a middleman. For example, if your intranet was setup to accept connections from my.example.org and you were on your localhost externally, you could proxy from your localhost to my.example.org which would then relay requests/responses to/from the intranet server.

So my advice to you would be to first ensure that the intranet can accept external connections, test with Postman until this works. Only then should you revisit your Vue app and make any changes to configuration if needed.

Thanks for your reply. The problem is resolved finally. As mentioned in my problem statement above, it was due to this custom instance of axios which was created. Removing this custom instance of axios ( https://forum.vuejs.org/t/api-proxying-and-axios/27966/5?u=vuebeginner) with normal axios dependency and adding proxy details to interact with backend in vue.config.js resolved the issue.

However this leads to me to an interesting development, i am facing a CSP (content security policy) issue when redirecting a oauth success to the client back. Any suggestion as to how i need to call the VueJS component from the server side? Currently I am redirecting the URL as follows.

          if (tokens) {
            req.session = {};
            req.session.accessToken = token;
            req.session.TokenSecret = secret;
            // res.header("Content-Security-Policy", "default-src 'self' https://192.168.XX.XX:8080");
            res.redirect("http://192.168.XX.XX:8080/success");
         //res.redirect("http://app.webApp.com/success");

Note, /success redirects to a Vue component.
It was working fine before this proxy setup. Please find the working flow depicted in the diagram below:
CSPIssuePicture

The CSP error as seen in the browser console:

Tried implementing the solutions from the following link: javascript - Content Security Policy: The page's settings blocked the loading of a resource - Stack Overflow, but its still not working. Please advice. Thanks in advance :slight_smile: