nuxt-community / axios-module

Secure and easy axios integration for Nuxt 2
https://axios.nuxtjs.org
MIT License
1.19k stars 245 forks source link

[Multi tenant] How to tell Axios to use the current domain instead of current host #529

Closed sneakylenny closed 3 years ago

sneakylenny commented 3 years ago

Hello I'm building a multi tenant Nuxt app that uses an API on the same domain but on the /api endpoint. The tenants are determined by subdomain. To give you some context here is the Apache setup:

Apache vhosts ```xml # Laravel API server ServerName web.site ServerAlias *.web.site DocumentRoot "C:/wamp64/www/WebSite-api/public" Options +Indexes +Includes +FollowSymLinks +MultiViews AllowOverride All Require all granted # Server pointing to Nuxt app and redirecting '/api' on 'subdomain1' to Laravel API ServerName subdomain1.web.site ProxyPass /api/ http://subdomain1.web.site:8081/api/ ProxyPass / http://localhost:8090/ ProxyPassReverse / http://localhost:8090/ ```

Now the issue I have is trying to set the Axios baseURL... I tried using this.$auth.loginWith("local", { ... }) but it sent the request to the hosting Nuxt server (http://localhost:8090/api/v1/login) instead of the current domain (http://tenant1.web.site/api/v1/login). But I want it to be sent to http://tenant1.web.site/api/v1/login. I tried a static solution by calling $axios.setBaseURL('http://tenant1.web.site/api/v1') which works and the request goes to the server and receives a response back. But since the tenant can vary on production I need to set the baseURL dynamically. I did a bunch of attempts to do this, but without success. I will explain some I still can remember:

In my store I have nuxtServerInit that checks with the server if a tenant exists and sets the tenant to store if it does or else redirect to home:

export const actions = {
  async nuxtServerInit(state, context) {
    if (!state.tenant) {
      const tenant = await this.$axios.$get('http://' + context.req.headers['x-forwarded-host'] + process.env.API_ENDPOINT + '/tenant').catch((error) => {
        if (error.code == 'ENOTFOUND') {
          context.redirect('http://hab.desk')
        }
      })
      state.commit('setTenant', tenant);
    }
  }
}

I did this to I could set the tenant in the domain that exists in the API.

Attempt 1: Setting it in nuxtServerInit:

// After state.commit('setTenant', tenant) 
this.$axios.setBaseURL('http://' + tenant.domains[0].domain)

This did not set the baseURL on client and failed

Attempt 2: Setting it in middleware, plugin and module:

I tried setting it from middleware, plugin and module but middleware turned out to be running server side only and was unable to set state on client. Plugin and Modules could not update the client Axios baseURL before the login page was initialized.

The solution I'm after

I was hoping there was a way to tell Axios to use the current domain so requests can be made to a varying URL containing that variable subdomain. And thus reach my API server. But there is none (to my knowledge).

sneakylenny commented 3 years ago

I fixed it by creating a plugin that sets the URL on load like this:

export default function ({ $axios, env, req }) {
  // Set request URL to current domain and add prefix
  if (process.client) {
    $axios.setBaseURL(window.location.origin + env.NUXT_ENV_API_PREFIX)
  } else if (process.server) {
    $axios.setBaseURL('http://' + req.headers['x-forwarded-host'] + env.NUXT_ENV_API_PREFIX);
  }
}

Requests are now being sent to the right URL.