1. The background

Some time ago, I wanted to set up a pin robot in the group to remind me to write a weekly report regularly. However, I encountered a cross-domain situation, and the code is roughly as follows:

— index.js —

import axios from 'axios'
function sxx () {
    axios.post('https://oapi.dingtalk.com/robot/send?XXXXXXXX', {
        msgtype: 'text'.text: {
          content: '[SXX]: I am what I am, a different firework '
        }
      })
}
sxx ()
Copy the code

— webpack.config.js —

const path = require('path')
module.exports = {
    entry: './index.js'.devServer: {
        host: '0.0.0.0'.port: 8080
    },
    plugins: [
      new HtmlWebpackPlugin()
    ],
    output: {
      filename: 'main.js'.path: path.resolve(__dirname, './dist')}}Copy the code

The error message is as follows:

2. Review cross-domain knowledge

For cross-domain, this article in MDN: HTTP Access Control (CORS) is very clear. Interception of the very classic images (see the picture below), we visit the resources (PNG images and eOT fonts) of Domain-b.com in Domain-a.com, and the two resources will be trans-domain. At this time, the browser may block the sending of the two resource requests, or the cross-site requests may be normally sent. However, the return result is blocked by the browser, depending on the browser implementation.

What makes you say you blocked the request? By Charles can see a post request https://oapi.dingtalk.com/robot/send didn’t send at all, just a connect request (and if really send request, group will have certain robot of the news, the returned result is useless for me)

3. Change whether Origin can process cross-domains

Access-control-allow-origin can be set on the server side, but we can not let Dingding to add it, right? From the principle of cross-domain, the browser is to determine whether the request header origin combined with the url to determine whether cross-domain, then we can change the origin to fool the browser? HTTP headers host/referer/origin So, the code changes as follows: — index.js —

import axios from 'axios'
function sxx () {
    axios.post('https://oapi.dingtalk.com/robot/send?XXXXXXXX', {
        msgtype: 'text'.text: {
          content: '[SXX]: I am what I am, a different firework '}}, {headers: {'Origin': 'oapi.dingtalk.com'} })
}
sxx ()
Copy the code

However, an error was reported directly… Parsing to set unsafe header “Origin”

Stack Overflow gurus’ explanation of the paper’s error

4. Webpack’s devServer.proxy handles cross-domain

Devserver. proxy can proxy the URL in the development environment. I tried to bypass the cross-domain, and the request was successful

import axios from 'axios'
function sxx () {
    axios.post('/robot/send? XXXXXXXX', {
        msgtype: 'text'.text: {
          content: '[SXX]: I am what I am, a different firework '
        }
      })
}
sxx ()
Copy the code

— webpack.config.js —

const path = require('path')
module.exports = {
    entry: './index.js'.devServer: {
        host: '0.0.0.0'.port: 8080.proxy: {
            '/robot': {
                target: 'https://oapi.dingtalk.com'.secure: false.// Must be written when the protocol is HTTPS
                changeOrigin: true}}},//... omitted... too lazy
}
Copy the code

Key: if you add changeOrigin: true, you can cross a domain. Otherwise, you still can’t cross a domain. So the point is to understand why changeOrigin can cross domains

5. How does changeOrigin solve cross-domain problems

Teacher Dell said in the video that the changeOrigin field is to prevent the website from being crawled, and it will verify the origin of the request. If the origin of the request is not from the website, then the request cannot get the result, and it looks like the origin in the header has been changed. But didn’t we just try to change origin? See the documentation for the description of the changeOrigin field:

changeOrigin: change the origin of the host header to the target url

Still not sure, then check the source code (http-proxy/common.js) :

changeOrigin

In fact, the proxy is equivalent to Charles in devServer url agent, in SXX () after the execution of requests is http://0.0.0.0:8080/robot/send? XXXXXXXX, we are at 0.0.0.0:8080, of course, we do not limit the sending of such requests, then the devServer proxy through configuration to change the host to oapi.dingtalk.com, the request can proceed normally, the general situation is shown below:

6. Charles simulation

To test this idea, the use of Charles replace devServer. The proxy agent the url, for http://0.0.0.0:8080/robot/send? XXXXXXXX Breakpoint, change the host of the request. But again, an error… The following figure

‘Invalid Host header’ in Stack Overflow
disableHostCheck: true