Stop sending preflight requests from axios.post

12,892

Solution 1

I found the solution for my query. As I mentioned above, our browser sends preflight request (means options request) before any other request if our request is not simple (here simple means: if request contains content-type : application/json or custom headers etc) and if we are sending this request to some other domain/ URL.

And our axios.post method carries content-type as application/json by default, that's why, my browser was sending multiple requests (means preflight request before any other request).

Now, I have changed my request content-type to application/x-www-form-urlencoded by sending data as params, as shown below:

     var params = new URLSearchParams();
                params.append('username', values.email);
                params.append('password', values.password);

            const response = await axios.post(ps.user_ms_url+ps.user_login,
                params);

And handling this request at backend using @ModelAttribute annotation (Spring-boot). So, keeping request simple can stop preflight requests.

Solution 2

You can avoid CORS preflight request by proxying the request. Add this in your webpack development config

  devServer: {
    port: process.env.PORT || 3000,
    proxy: {
      '/api': {
        target: 'http:localhost:8080',
        pathRewrite: { '^/api': '' },
        changeOrigin: true,
      },
    },
  }

This means your request to /api/users will forwarded to http://localhost:8080/users.

If you are using create-react-app. just add "proxy": "http://localhost:8080" to your package.json. Check more info here

Share:
12,892
Balram Chauhan
Author by

Balram Chauhan

Updated on June 04, 2022

Comments

  • Balram Chauhan
    Balram Chauhan almost 2 years

    I have my micro-service developed using spring-boot and spring security and frontend is designed on react-hooks. Now, while I am send some data to my micro-service using axios.post method, it send CORS preflight method i.e. options method because axios by default send content-type as application/json and application.json leads to send options request to server before any other request.

    I have tried sending my request with different headers and content types as 'application/x-www-form-urlencoded' also I have used @cross-origin(*) at my server end.

    const config = {
                        headers: {
                        'Content-Type': 'application/json'
                        }
                    }
    
                const response = await axios.post(ps.user_ms_url+ps.user_login,
                    {
                        username:values.email,
                        password:values.password
                        // headers:{'tokenvalue':'token'}
    
                    },
                    config);
    

    I expect my browser to send only post request to the server, for that I am ready to change my headers as well. Any help will be appreciated. Thanks in advance!

    • Jasper Bernales
      Jasper Bernales over 4 years
      This is expected to happen if you are requesting from different domain. Are you using create-react-app for your react app? there's a way to get a way with CORS using proxy and builtin create-react-app
  • Balram Chauhan
    Balram Chauhan over 4 years
    Thank you for your prompt reply. And you are right as I am requesting from different domain but I didn't understand your answer. Like, how i will be able to stop preflight methods by proxing the request as I am already able to hit the URL.
  • Balram Chauhan
    Balram Chauhan over 4 years
    Yes, I have already provided access to * at my server end as I have provided: @CrossOrigin("*") annotation at my URL mapping which allows all the request domains to hit URL
  • Jasper Bernales
    Jasper Bernales over 4 years
    are you using webpack?
  • Balram Chauhan
    Balram Chauhan over 4 years
    no, I'm not using webpack but yes, I m using create-react-app for my react app
  • Jasper Bernales
    Jasper Bernales over 4 years
    as i said add this to your package.json "proxy": "http://localhost:8080" then add '/api' prefix to your requests to backend
  • Balram Chauhan
    Balram Chauhan over 4 years
    I applied proxy in my package.json but it didn't work for me. And can you please tell how will it work to stop options request?
  • Jasper Bernales
    Jasper Bernales over 4 years
    as I said add prefix '/api' to your requests. so instead of http://localhost:8080/login (i dont know what the value of this ps.user_ms_url+ps.user_login) you replace the url with /api/login this means that your webpack-dev-server is proxying the request to your backend
  • Balram Chauhan
    Balram Chauhan over 4 years
    I understand that but as in my case I am runnning my front end at localhost:3000 and backend at localhost:8090/someurl/someotherurl/login.... So, as per your solution, I should add a line "proxy": "localhost:8090" in my package.json and I will hit url with "/someurl/sopmeotherurl/login".... Am I right?
  • Jasper Bernales
    Jasper Bernales over 4 years
    here it is step by step. 1) add this to package.json "proxy": "http://localhost:8090 . 2) repalce this /someurl/sopmeotherurl/login with this/api/someurl/sopmeotherurl/login
  • Balram Chauhan
    Balram Chauhan over 4 years
    Yes, I have applied exact code as you said but now it is hitting the URL as localhost:3000/api/someurl/sopmeotherurl/login
  • Jasper Bernales
    Jasper Bernales over 4 years
    yes that's actually what we want. webpack-dev-server should proxy your request to your backend. check your backend logs if it hits your server. what is actually the route for the login in your backend?
  • Balram Chauhan
    Balram Chauhan over 4 years
    No, It is enable to hit my backend server and Route to my backend login service is : localhost:8090/someurl/someotherurl/login and what exactly my browser hitting is: http:/localhost:3000/api/someurl/someotherurl/login
  • Balram Chauhan
    Balram Chauhan over 4 years
    correction- not able* (it is not able to hit server)
  • Jasper Bernales
    Jasper Bernales over 4 years
    I see my mistake. please take a look at this sandbox. https://codesandbox.io/s/ecstatic-sutherland-o7gql There's a file setupProxy.js copy it under your src and edit the target. it should work if you are using [email protected] or higher
  • Balram Chauhan
    Balram Chauhan over 4 years
    I did as you said and your proxy is working properly. Now, my browser is hitting localhost:3000 instead of server address which is localhost:8090 and I am able to login successfully. That's good, proxying is implemented as you said but still my browser is sending 3 requests on login click, it is sending preflight request as well. And I am looking for solution to avoid multiple requests on single click and one more thing when I enter right credentials then it sends only 1 request and if I enter wrong credentials it sends 3 requests including preflight request...
  • Jasper Bernales
    Jasper Bernales over 4 years
    you should use /api/ prefix on all your request. i don't think the request with preflight is proxied.
  • Jasper Bernales
    Jasper Bernales over 4 years
    let me know if it works and please accept my answer. thanks!
  • Balram Chauhan
    Balram Chauhan over 4 years
    your proxy is implemented successfully but it is not able to stop preflight requests as I said in my question. I don't want proxified requests if it is sending OPTIONS request before POST request.