93

I was trying to follow the docs and created vite.config.js like this:

const config = {
  outDir: '../wwwroot/',
  proxy: {
    // string shorthand
    '/foo': 'http://localhost:4567',
    // with options
    '/api': {
      target: 'http://jsonplaceholder.typicode.com',
      changeOrigin: true,
      rewrite: path => path.replace(/^\/api/, '')
    }
  }
};

export default config;

And tried to test it with following calls:

fetch('/foo');
fetch('/api/test/get');

I was expecting to have actual requests as http://localhost:4567/foo and http://jsonplaceholder.typicode.com/test/get But both of them had my dev server as an origin like this: http://localhost:3000/foo and http://localhost:3000/api/test/get

Did I misunderstand it? How proxies should work?

I also created an issue in the Vite repo but it was closed and I did not understand the closing comment.

1
  • 3
    The client (browser or whatever) always requests from localhost:3000, so all your fetches will go to localhost:3000. Then your server (which runs on localhost:3000) will delegate the calls of '/foo' and '/api/...' to the provided urls and delegate their answer to your client. From the point of view of the client, the request targets localhost:3000 and from that url it also receives the response. Commented Oct 6, 2023 at 10:30

7 Answers 7

89

For debugging I highly recommend to add event listeners to the proxy, so you can see how the requests are transformed, if they hit the target server, and what is returned.

export default {
  server: {
    proxy: {
        '/api': {
          target: 'https://localhost:44305',
          changeOrigin: true,
          secure: false,      
          ws: true,
          configure: (proxy, _options) => {
            proxy.on('error', (err, _req, _res) => {
              console.log('proxy error', err);
            });
            proxy.on('proxyReq', (proxyReq, req, _res) => {
              console.log('Sending Request to the Target:', req.method, req.url);
            });
            proxy.on('proxyRes', (proxyRes, req, _res) => {
              console.log('Received Response from the Target:', proxyRes.statusCode, req.url);
            });
          },
        }
      }
  }
};

proxy will be an instance of 'http-proxy', Please see for further info https://github.com/http-party/node-http-proxy#options

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

6 Comments

Where do these logs actually go? I don't see anything in the console
The go into the standard console. Does the search path/regex in the first line (the '/api') match? Probably it doesn't so the whole block doesn't get called, hence no console message.
Thanks for the tip, was brilliant! On top of that, in this proxy can also override headers returned by the server, so you can skip ContentSecurePolicies, and force cookies "set by the server" by SetCookie, etc with res.setHeader(key, value)
@Marcosaurios I never thought about overriding headers this way, thanks for this awesome feedback!
@user2138149 if you are running in visual studio the logs will not print out in visual studios output console like i was expecting. I thought the logs were not working. Instead the logs will print out in the command window that VS launches and this window often launches behind visual studio. I did not see until 4 hours into troubleshooting this proxy and just thought the proxy was not working at all the entire time.
|
70

Turns out it's needed to specify secure flag to false like this:

Vite at your sample:

Related github issue

 proxy: {
      '/api': {
           target: 'https://localhost:44305',
           changeOrigin: true,
           secure: false,      
           ws: true,
       }
  }

Vite at 2024:

export default defineConfig({
  server: {
    proxy: {
      '/foo': 'http://localhost:4567',
      '/api': {
        target: 'http://jsonplaceholder.typicode.com',
        changeOrigin: true,
        secure: false,
      },
    },
  },
  // some other configuration
})

4 Comments

Does this only work in development? What would be the alternative for achieving exactly the same behaviour but in production?
@FalconStakepool In production, have a proxy server like nginx or AWS ALB in front to handle serving some traffic to the frontend and other traffic elsewhere
The second route needs the path rewrite, otherwise nothing get's rendered (at least for me). From the docs: rewrite: (path) => path.replace(/^\/api/, '')
55

Based on the Vite Config you need to specify it via server -> proxy inside vite.config.js:

export default defineConfig({
  server: {
    proxy: {
      "/api": {
        target: "https://your-remote-domain.com",
        changeOrigin: true,
        secure: false,
      },
    },
  },
  // some other configuration
})

1 Comment

Where do I specify the logging and how?
8

suppose https://localhost:44305 is the backend and port 3000 is the frontend.

I guess the Vite document is kind of confusing.

When I set '/api' : {target: 'https://localhost:44305'}, it actually redirects to http://localhost:44305/api for http://localhost:3000/api instead of redirecting to https://localhost:44305/.

so if you use axios.get(), it should be set to 'axios.get('/api/something')' for the backend server, http://localhost:44305/api/something

Hope this trick is helpful.

1 Comment

That's why you use the rewrite field: rewrite: (path) => path.replace(/^\/api/, ''), vite.dev/config/server-options.html#server-proxy
5
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
  server: {
    proxy: {
      '/api':'http://localhost:5000',
    },
  },
  plugins: [react()],
});

// this is the only method that worked for me, you don't need all the parameters such as target, secure and everything just the above code is enough in your vite.config.js file and make sure you give the local host port number of your server in the /api.

Comments

3

This Config Worked for me.

Without rewrite, it did not work for me.

// App Axios: /foo/people
// Response From: https://www.swapi.tech/api/people  

server: {
      port: PORT,
      proxy: {
        "/foo": {
          target: "https://www.swapi.tech/api",
          changeOrigin: true,
          secure: true,
          rewrite: (path) => path.replace(/^\/foo/, ""),
        },
      },
    },

1 Comment

That's also working for me, thank you! When using the fetch API, if you perform a fetch('/foo/my/nice/endpoint/',{...}) from your component it calls the swapi.tech/api/my/nice/endpoint
2
export default defineConfig({
  plugins: [vue()],
  server: {
   port: 8080,
   proxy:{
   '/posts': 'https://jsonplaceholder.typicode.com'
   }
  }

})

3 Comments

Restart your server with provided port number. if issues persists then reload the page
Thank you for your interest in contributing to the Stack Overflow community. This question already has a few answers—including one that has been extensively validated by the community. Are you certain your approach hasn’t been given previously? If so, it would be useful to explain how your approach is different, under what circumstances your approach might be preferred, and/or why you think the previous answers aren’t sufficient. Can you kindly edit your answer to offer an explanation?
I reckon this works with the latest version of Vite. I used this while connecting to a NodeJS server. Thanks!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.