nuxt-community / legacy-modules

MIT License
1.29k stars 157 forks source link

baseURL works as expected from asyncData, not from client components #39

Closed riteable closed 7 years ago

riteable commented 7 years ago

When I call app.$axios.get('/') from asyncData() the actual request goes to the URL /api. This works as expected.

But when I call this.$axios.get('/') from methods or from the store, the request is being sent to "/"

Is this the correct behavior?

This bug report is available on Nuxt.js community (#c7)
pi0 commented 7 years ago

Hi. First do you confirm using 2.1.0 version of axios? problem may resolve with that. Also how do you use it from store?

riteable commented 7 years ago

Just updated to 2.1.0. Issue is resolved.

Thanks!

pi0 commented 7 years ago

@riteable I've checked against latest release here: https://glitch.com/edit/#!/mica-bulb + https://mica-bulb.glitch.me/ and it seems working as expected. Please check this out to make sure every thing is same as this demo.

SSR Activity log:

asyncData: http://localhost:3000/api
fetch: http://localhost:3000/api
created: http://localhost:3000/api

Web:

created: /api
index.vue:19 mounted: /api
index.vue:12 asyncData: /api
index.vue:16 fetch: /api
index.vue:22 created: /api
index.vue:19 mounted: /api

// Click on login
login action: /api
pi0 commented 7 years ago

Appendix: I'm pretty sure you are facing problem because not upgraded correctly (double check it from node_mdouels, and also clean up .nuxt dir and restart nuxt dev)

renatocf commented 7 years ago

Hi, I'm having a similar problem.

I'm using localhost:4200 for my nuxt dev server because my API is in localhost:3000. I set PORT to 4200 to change the default server URL. In order to use Axios, I changed baseUrl to http://localhost:3000 in nuxt.config.js, but when I log $axios.defaults.baseURL as in your example, it always prints http://localhost:4200/api. If I manually set API_URL when running the server, it works as expected. However, setting this option in nuxt.config.js within the axios section doesn't work.

This is my full nuxt.config.js (originally generated by the nuxt/starter template):

module.exports = {
  /*
  ** Headers of the page
  */
  head: {
    title: 'starter',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: 'Nuxt.js project' }
    ],
    link: [
      { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
    ]
  },
  /*
  ** Customize the progress-bar color
  */
  loading: { color: '#3B8070' },
  /*
  ** Build configuration
  */
  build: {
    /*
    ** Run ESLINT on save
    */
    extend (config, ctx) {
      if (ctx.isClient) {
        config.module.rules.push({
          enforce: 'pre',
          test: /\.(js|vue)$/,
          loader: 'eslint-loader',
          exclude: /(node_modules)/
        })
      }
    }
  },
  modules: [
    '@nuxtjs/axios',
    '@nuxtjs/bootstrap-vue',
    '@nuxtjs/font-awesome'
  ],
  axios: {
    baseUrl: 'http://localhost:3000'
  }
}

Here it's my package.json (I've updated @nuxtjs/axios to the latest version):

{
  "name": "nrdr",
  "version": "1.0.0",
  "description": "Nuxt.js project",
  "author": "",
  "private": true,
  "dependencies": {
    "@nuxtjs/axios": "^2.1.0",
    "@nuxtjs/bootstrap-vue": "^1.0.4",
    "@nuxtjs/font-awesome": "^1.0.1",
    "@nuxtjs/proxy": "^1.1.1",
    "nuxt": "1.0.0-alpha.4"
  },
  "config": {
    "nuxt": {
      "host": "0.0.0.0",
      "port": "4200"
    }
  },
  "scripts": {
    "dev": "nuxt",
    "build": "nuxt build",
    "start": "nuxt start",
    "generate": "nuxt generate",
    "lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
    "precommit": "npm run lint"
  },
  "devDependencies": {
    "babel-eslint": "^7.1.1",
    "eslint": "^3.15.0",
    "eslint-config-standard": "^6.2.1",
    "eslint-loader": "^1.6.1",
    "eslint-plugin-html": "^2.0.0",
    "eslint-plugin-promise": "^3.4.1",
    "eslint-plugin-standard": "^2.0.1"
  }
}

I've also tried to use @nuxtjs/proxy to redirect the URL, mapping /api to http://localhost:3000 in the proxy section within nuxt.config.js and leaving the Axios configuration as the default, but it didn't work either.

pi0 commented 7 years ago

@renatocf Sorry i still didn't succeed reproduce this issue locally will try to investigate more. Meanwhile if you could remix my glitch example, reproducing your problem would help a lot for faster support.

renatocf commented 7 years ago

@pi0, thanks for your help! I created a repo using nuxt/starter and created a working example of the problem: https://github.com/renatocf/axios-glitch. The steps to reproduce the problem are described in the end of the README.

As in my main repository, I changed Nuxt server's port to 4200. I also provided a small external API (using json-server) to direct Axios' requests. These requests are made in an action of the Vuex store (I think the store isn't important for this issue, but that's how I'm retrieving the data in my main program).

pimlie commented 7 years ago

It seems I was experiencing a similar issue, I finally tracked the cause to a wrong host header being set on my component requests. Setting proxyHeaders: false was a quick workaround for me.

Enabling proxyHeaders blindly copies all headers from the server to the client, thats probably fine for most headers but host is a special case.

A possible fix for this would be (this resolves my issue)

<% if(options.proxyHeaders) { %>headers: (req && req.headers) ? Object.assign({}, req.headers, {host: ''}) : {} <% } %>

Please check, if this works for you too I will create a PR for this

pi0 commented 7 years ago

@pimlie Good catch. What's your idea removing Host header by default?

pimlie commented 7 years ago

Not sure what you mean with by default?

The host header is required for a valid request, but normally nodejs/http_client:174 would set that header based on the url passed. So by removing the host header on our side, we make sure that http_client sets the correct host header based on the url we request. Setting host to an empty string (also when it not exists) should not be a problem as an empty string evaluates to false.

--edit-- Fyi, I looked at using e.g. delete req.headers.host or closures instead of Object.assign but I think this is the easiest solution. This is mainly because we don't want to manipulate the original context object.

renatocf commented 7 years ago

@pimlie, thanks for your help! I'm not sure where I should insert this piece of code you recommended me. And in which file did you put proxyHeaders: false?

renatocf commented 7 years ago

So, I realized that @pimlie's code should go in the module's index.js file. Unhappily, setting proxyHeaders: false didn't work for me. I investigated a little bit further and it seems that the options from nuxt.config.js are being completely ignored when the module is loaded. In:

module.exports = function nuxtAxios (moduleOptions) {
   // ...
}

Shouldn't the variable moduleOptions be the object representing these options? I tried to log it and it is empty! This way, the line const options = Object.assign({}, defaults, this.options.axios, moduleOptions)makes options to be a copy of defauls.

Who should be calling the function nuxtAxios?

Edit: All the tests were made in my repository https://github.com/renatocf/axios-glitch

pi0 commented 7 years ago

@renatocf moduleOptions can be passed like this:

modules: { 
   ['@nuxtjs/axios', { proxyHeaders: false }],
}

Disabling proxyHeaders should fix your problem, i will fix root cause in next update

renatocf commented 7 years ago

Ok guys, this one will enter to my personal list of "moments that programming made me feel stupid".

I had no problem with proxyHeaders, I was setting the wrong variable in nuxt.config.js the whole time! Instead of setting browserURL (with capitalized URL), I was setting browserUrl (with just U capitalized). I logged the variable options in the console after the Object.assign and then I realized it had two very similar parameters browserURL and browserUrl.

Thanks for your help, now my program works perfectly.