1.跨域 #

2. CORS(跨源资源共享) #

请求头 说明
Access-Control-Allow-Origin 指定哪些网站可以参与跨源资源共享,"*" 表示所有网站都可以
Access-Control-Allow-Methods 指定了允许进行跨源请求的方法,如 GET,POST,DELETE 等
Access-Control-Allow-Headers 指定了可以使用哪些 HTTP 头字段进行跨源请求
Access-Control-Allow-Credentials 表示是否允许发送 Cookie
const http = require('http');
const server = http.createServer((req, res) => {
  res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:5500');
  res.setHeader('Access-Control-Allow-Credentials', 'true');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
  // 读取cookie
  let cookies = req.headers['cookie'];
  console.log('Cookies: ', cookies);
  // 设置cookie
  res.setHeader('Set-Cookie', ['id=1', 'age=18']);
  res.statusCode = 200;
  res.end('hello');
});
server.listen(3000, () => console.log(`Server is listening on port 3000`));
<body>
    <script>
        let xhr = new XMLHttpRequest();
        xhr.open('POST', 'http://127.0.0.1:3000/users', true);
        xhr.withCredentials = true;
        xhr.setRequestHeader('Content-Type', 'application/json');
        xhr.onload = function () {
            if (xhr.status === 200) {
                console.log(xhr.responseText);
            }
        }
        xhr.send(JSON.stringify({ name: 'New User', age: 20 }));
    </script>
</body>

3. JSONP #

3.1 工作原理 #

3.1.1 jsonp-server.js #

const http = require('http');
const url = require('url');
const server = http.createServer((req, res) => {
    const queryObject = url.parse(req.url,true).query;
    const callbackFunction = queryObject.callback;
    const data = { message: 'Hello, JSONP!' };
    res.writeHead(200, { 'Content-Type': 'text/javascript' });
    res.end(`${callbackFunction}(${JSON.stringify(data)})`);
});
server.listen(3000, () => {
    console.log('Server listening on port 3000');
});

3.1.2 jsonp-html.html #

<!DOCTYPE html>
<html>
<body>
    <h1>JSONP</h1>
    <button onclick="fetchData()">Fetch Data</button>
    <script>
        function myCallback(data) {
            console.log('Received data: ', data);
        }
        function fetchData() {
            const script = document.createElement('script');
            script.src = 'http://localhost:3000?callback=myCallback';
            document.body.appendChild(script);
        }
    </script>
</body>
</html>

3.2 百度搜索 #

3.2.1 搜索接口 #

https://www.baidu.com/sugrec?prod=pc&wd=hello&cb=jQuery1102039950249152921513_1684412625594&_=1684412625601

3.2.2 jquery请求 #

<body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script>
        $.ajax({
            url: "https://www.baidu.com/sugrec",
            jsonp: "cb",
            dataType: "jsonp",
            data: {
                prod: "pc",
                wd: "hello"
            },
            success: function(response) {
                console.log(response);
            }
        });
    </script>
</body>

3.2.3 封装jsonp #

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
    <input id="search-input" type="text" placeholder="搜索关键词">
    <ul id="suggestion-list"></ul>
    <script>
        function jsonp({ url, jsonp, data }) {
            return new Promise((resolve, reject) => {
                // 创建一个全局函数来接收回调数据
                let callbackName = `jQuery_${Date.now()}`;
                window[callbackName] = function (result) {
                    delete window[callbackName];  // 删除这个临时函数
                    document.body.removeChild(script);  // 删除这个临时script标签
                    resolve(result);
                };
                // 将数据参数转换为url参数字符串
                let queryStr = url.indexOf('?') === -1 ? '?' : '&';
                for (let key in data) {
                    queryStr += `${key}=${data[key]}&`
                }
                // 创建一个script标签,然后通过该标签的src属性去请求服务端,服务端接收请求后返回一段调用全局函数的js代码
                let script = document.createElement('script');
                script.src = `${url}${queryStr}${jsonp}=${callbackName}`;
                document.body.appendChild(script);
            });
        }
        document.getElementById('search-input').addEventListener('input', function (e) {
            jsonp({
                url: "https://www.baidu.com/sugrec",
                jsonp: "cb",
                data: {prod: "pc",wd:e.target.value}
            }).then(response => {
                const suggestions = response.g || [];
                const suggestionList = document.getElementById('suggestion-list');
                let html = '';
                for (let i = 0; i < suggestions.length; i++) {
                    html += `<li>${suggestions[i].q}</li>`;
                }
                suggestionList.innerHTML = html;
            });
        });
    </script>
</body>
</html>