Ajax & CORS in React

  1. Ajax requests in React

    React needs to integrate a third-party ajax library or package it yourself. Generally use axios.


  2. Reason for Proxy

    cross domain

    If the proxy is not configured, cross-domain issues will occur (No ‘Access-Control-Allow-Origin’ header…). The reason for the cross-domain is that the address of the Client is http://localhost:3000 and the address of the server is http://localhost:5000 , so the ajax request is not allowed.

    In addition, the request can be sent out when cross-domain (the server can receive the request), but the ajax engine prevents the data from being returned when it comes back.


    Solve cross-domain in React scaffolding

    Scaffolding proxy is a middleman (tiny server), it is opened on port 3000, when Client (3000) sends a request to Server (5000), it first sends the request to The proxy intermediary (3000) is established, and then the proxy intermediary (3000) forwards the request to the Server (5000). When the Server (5000) returns the data, the agent intermediary (3000) receives the data first, and then forwards it to the Client (3000).

    Although the proxy middleman (3000) is opened on port 3000, it does not use the ajax engine. Because the essential problem of cross-domain is that the ajax engine blocks the response, and the intermediary without the ajax engine has no cross-domain problem, and the same-origin policy does not limit it.


  3. Scaffolding proxy configuration

    There are two ways to configure proxies in React.

    1. Global proxy (single server)

      In the package.json file, add the proxy attribute at the end of the file. The key value is the address to which the request is to be forwarded, just write the port number. Do not write specific / items, such as /students, it will cause the address to be dead. After configuration, all requests sent to 3000 in the client will be forwarded to 5000. Note here that the scaffolding needs to be restarted after setting.

      1
      2
      },
      "proxy":"http://localhost:5000"

      After configuration, the Client code must only send requests to port 3000.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
         getStudentData = () => {
      axios.get('http://localhost:3000/students').then( //Note that this is for 3000
      response => {console.log(response.data);},
      error => {console.log(error);}
      )
      }
      ``

      <br/>

      Note that not all requests sent via http://localhost:3000 are forwarded to the Server (5000). If the item followed by 3000/request is the file under the <font color='red'>public folder</font> of this project, such as http://localhost:3000/index.html, it will get the public file . <font color='red'>This is because the public folder is the root path of 3000 in http://localhost:3000. </font>Some resources in 3000 will not be forwarded to 5000 by the agent.

      <br/>

      2. <font color='green'>Multi-Server Agent</font>

      There is a problem with a single-server proxy, because only one proxy server address can be configured. If the project is to get data from different servers, configuring a proxy cannot meet the needs.

      Before configuring, make sure there is no proxy configuration in package.json.

      <br/>

      <font color='red'>Configuration method: Create the setupProxy.js file in the src folder (the file name cannot be changed). </font> The code in the file cannot use ES6, but use CJS. Because this file is scaffolded into webpack, which is node.js syntax. (The code does not need to be mastered)

      <br/>

      ```javascript
      const proxy = require('http-proxy-middleware') //This package has been downloaded when the react scaffold is initialized.
      // The global proxy is just a shorthand version of it
      module.exports = function(app){
      app.use(
      proxy('/api1',{ //parameter 1, when a request with this prefix is encountered, the configuration of the proxy will be triggered
      target:'http://localhost:5000', //To whom the request is forwarded
      changeOrigin:true, //Let the server know exactly where the request came from. The default is false, and it is changed to true
      pathRewrite:{'^/api':''} //Key-value pair, the key name is the prefix to be replaced, and the key value is empty after the replacement (required)
      }),
      proxy('/api2',{
      target:'http://localhost:5001', //Second server
      changeOrigin:true,
      pathRewrite:{'^/api':''}
      }),
      )
      }

      proxy() accepts two parameters. The first parameter is the path, that is, if the request in the project contains this path, it will be forwarded to the specified server. The second parameter is an object, the forwarding target server and configuration.


      The pathRewrite:{'^/api':''} in the second parameter is to fix the path where the client sends the request. In parameter 1, the proxy sets the identification path, so the address requests sent by the Client to the target server all have /api1 (to allow the proxy to identify the server to be forwarded). However, after adding the identification path /api, the request address is wrong. pathRewrite:{'^/api':''} can replace the identification path /api in the request address (after locating the forwarding server) with empty, so the address can be repaired to the server address.


      The changeOrigin:true, in the second parameter is used to control the value of the Host field in the request header received by the server. The Host field identifies where the request is sent from. Without adding changeOrigin:true,, the Host obtained by the server is 3000, and the data cannot be obtained if the server is strictly restricted. After adding changeOrigin:true,, the Host obtained by the server is 5000. Therefore, this configuration is generally added.


      Also note that every time you modify the configuration proxy file or modify the server file, you must restart the scaffolding/server.


      Axios request code should be written as:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      getStudentData = () => {
      axios.get('http://localhost:3000/api1/students').then( //Identify the path api1
      response => {console.log(response.data);},
      error => {console.log(error);}
      )
      }
      getCarData = () => {
      axios.get('http://localhost:3000/api2/cars').then( //Identify the path api2
      response => {console.log(response.data);},
      error => {console.log(error);}
      )
      }

      It means that if there is no students data in the request sent to localhost:3000 (local), go to the proxy configured by api1.


  4. Simplified request address

    If the client location (3000) is the same location as the destination location of the request, you can omit http://localhost:3000. Note here that the reason why the 3000 address sends a request to the 3000 address is that the proxy is set, and the address sent to 3000 is transferred to 5000.

    1
    2
    axios.get('http://localhost:3000/api1/search/user?q=${keyWord}').then() //Before simplification
    axios.get('/api1/search/user?q=${keyWord}').then() //simplified

Share