nuxt-community / axios-module

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

practical proxy question #126

Open husayt opened 6 years ago

husayt commented 6 years ago

Axios module working with proxy module offers a lot of great features. Main problem is lack of examples to bring these features to surface, I am sure most of users don't even know about 90% of those features.

For example I have this requirement:

My nuxt website needs to connect to http://dataserver:com:4444. I have two setups: 1) in dev mode nuxt server running on http://locahost:3000 with /api proxying to http://dataserver:com:4444 1) in prod mode website is statically generated (via generate) and deployed to run on http://dataserver:com:80 with /api proxying to http://dataserver:com:4444

So call to

this.$axios.$get(`api/orders`)

should call http://dataserver:com:4444/orders if it is prod mode or if it SSR in dev mode. On client side call of dev mode it should call http://locahost:3000/api/orders (which is a proxy url for http://dataserver:com:4444)

This is my config

  axios: {
    proxy: true,
    baseURL: 
      process.env.NODE_ENV !== "production"
        ? `http://${host}:${port}`
        : "http://dataserver:com:4444"
  },
  proxy: {
     "/api": {
      target: "http://dataserver:com:4444/",
      pathRewrite: { "^/api": "" },
      changeOrigin: false,
      prependPath: false
    }
  },

What am I missing? It works as expected in dev mode, but in in prod mode it calls http://dataserver:com:4444/api/orders, instead of http://dataserver:com:4444/orders (Notice extra api in the url)

This question is available on Nuxt.js community (#c106)
mdsaudali365 commented 6 years ago

@husayt,

I was stuck on axios and proxy module implementation in my project, but your question cleared the path for me. I totally agree with you that it would be great to have some officially integrated examples:)

zoellner commented 5 years ago

I was also missing some data flow diagrams to wrap my head around where all the prefix and proxy magic is happening and which configuration option takes precedence.

Another missing piece is the port configuration when using something other than 3000 for local dev since it seems to be hardcoded in a few places. E.g. for nuxt itself it is sufficient to set server.port or env.PORT in nuxt.config.js but the axios module seems to ignore those and still use 3000. It has to be set at the npm level to work - a note about that should be added to the documentation that mentions

Can be customized with API_PREFIX, API_HOST (or HOST) and API_PORT (or PORT) environment variables.

That is actually not quite correct anyways since setting API_PREFIX has no effect if API_URL is set but proxy is not enabled. It does only work when either API_HOST is not set (then used for both baseUrl as well as browserBaseURL) or when set but also proxy enabled (then used for browserBaseURL).

One more gotcha is that while the documentation for axios options lists baseUrl it can't actually be set using axios.baseUrl in nuxt.config.js. It's basically a read-only option that can only be set through yet another environment variable that has to be at the npm level - API_URL. Somewhat unfortunate naming here as well since axios' baseUrl is the baseUrl for the API but nuxt baseUrl is for the nuxt backend which might be different servers.

Also missing an explanation on how to setup different targets based on the environment (dev/prod). I believe this isn't easily possible through nuxt.config.js but has to be done through npm-level environment variables.

Another useful hint in the documentation would be for debug logging using the environment variable DEBUG=nuxt:*

My final Setup

The final configuration for me is as follows, hope it helps others.

At this point both client as well as server side API calls correctly use the specified API_URL. Now, in order to simplify things in production when CORS is an issue, the base url for client side requests (what axios calls browserBaseURL) needs to be changed and this is where proxy enters the game. For that I add to the configuration (in nuxt.config.js axios):

In production I can now set a different API_URL environment variable to point to the production API backend (say the frontend is at example.com and the backend at api.example.com). And if I don't want to hit the nuxt backend (running at example.com/api/) with every API request that originates on the client, I can configure my CDN to route requests to /api/ directly to the API backend and therefore reduce the load on the nuxt backend server and save one network hop.

Amaurgit commented 4 years ago

Doesn't work with generated mode :( Did you manage to rewrite your url without api in static mode?

pisethx commented 4 years ago

My final Setup

The final configuration for me is as follows, hope it helps others.

  • Set environment variable PORT=8000 at npm level to have my frontend be served at 8000 instead of 3000 and make it work across all of nuxt and axios at the same time. Remove all other default port settings (namely nuxt.config.js env.PORT and server.port).
  • Set environment variable API_URL=http://localhost:8100 for an API Backend that is running locally at port 8100 - this can then easily be set to a different host/port in production

At this point both client as well as server side API calls correctly use the specified API_URL. Now, in order to simplify things in production when CORS is an issue, the base url for client side requests (what axios calls browserBaseURL) needs to be changed and this is where proxy enters the game. For that I add to the configuration (in nuxt.config.js axios):

  • proxy: true
  • prefix: '/api/' (or alternatively npm level environment variable API_PREFIX=/api/ which at this point has the same effect since proxy is enabled) The server side is unchanged, baseURL is still set through the environment variable but client side requests now go to http://localhost:8000/api/ (browserBaseURL is /api/). Now in order for nuxt to proxy those to the API backend at http://localhost:8100, the proxy setting in nuxt.config.js needs to be set. In this case to
  • proxy: {'/api/': { target: process.env.API_URL, pathRewrite: {'^/api/': ''} }} This will enable the proxy server at the nuxt backend (at 8080 for path /api/*) and forward those requests to the API_URL which has already been set for the requests originating server side.

In production I can now set a different API_URL environment variable to point to the production API backend (say the frontend is at example.com and the backend at api.example.com). And if I don't want to hit the nuxt backend (running at example.com/api/) with every API request that originates on the client, I can configure my CDN to route requests to /api/ directly to the API backend and therefore reduce the load on the nuxt backend server and save one network hop.

You are a fking legend, bro!

sbarfurth commented 4 years ago

What @zoellner wrote works. I found that surprising, it seems like this is exactly what I already had. The main difference seems to be the definition of API_URL over BASE_URL (or some other variable name) and the usage of a global prefix (or API_PREFIX) rather than prefixing paths in code.

farnabaz commented 3 years ago

@Amaurgit Proxy does not work in static projects (nuxt generate). Static projects does not ship server middle-wares to production, therefore server middleware of proxy module will not work on any static project.