当前位置: 首页 > news >正文

Angular由一个bug说起之十三:Cross Origin

跨域

想要了解跨域,首要要了解源

什么是源,源等于协议加域名加端口号

只有这三个都相同,才是同源,反之则是非同源。

比如下面这四个里,只有第4个是同源

而浏览器给服务器发送请求时,他们的源一样,就是同源请求,反之就是非同源请求,非同源请求又称为跨域。

当你是跨域时,浏览器为了确保资源安全,会对跨域的访问资源做出一些限制,也就是浏览器的同源策略。

这是W3C上对同源策略的说明:https://www.w3.org/Security/wiki/Same_Origin_Policy

浏览器会对跨域做出哪些限制?

例如:源a和源b,它们是非同源的,则浏览器会有如下限制:

1. DOM访问限制:源a的脚本不能读取和操作源b的DOM。

页面1

1.	<!DOCTYPE html>
2.	<html lang="en">
3.	<head>
4.	    <meta charset="UTF-8">
5.	    <meta name="viewport" content="width=device-width, initial-scale=1.0">
6.	    <title>Document</title>
7.	</head>
8.	<body>
9.	    <h1>我是页面1</h1>
10.	    <button onclick="showDOM()">获取页面2的DOM</button>
11.	    <br>
12.	    <iframe id="framePage" src="./demo.html"></iframe>
13.	    <!-- <iframe id="framePage" src="https://www.baidu.com"></iframe> -->
14.	
15.	    <script type="text/javascript" >
16.	        function showDOM(){
17.	            const framePage = document.getElementById('framePage')
18.	            console.log(framePage.contentWindow.document.body) //同源的可以获取,非同源的无法获取
19.	        }
20.	    </script>
21.	    </body>
22.	</html>

页面2

1.	<!DOCTYPE html>
2.	<html lang="en">
3.	<head>
4.	    <meta charset="UTF-8">
5.	    <meta name="viewport" content="width=device-width, initial-scale=1.0">
6.	    <title>Document</title>
7.	</head>
8.	<body>
9.	    <h2>我是页面2</h2>
10.	</body>
11.	</html>

页面是这样的

点击获取

换一个不同源的页面

1.	<body>
2.	    <h1>我是页面1</h1>
3.	    <button onclick="showDOM()">获取页面2的DOM</button>
4.	    <br>
5.	    <!-- <iframe id="framePage" src="./demo.html"></iframe> -->
6.	    <iframe id="framePage" src="https://www.bilibili.com"></iframe>
7.	
8.	    <script type="text/javascript">
9.	        function showDOM() {
10.	            const framePage = document.getElementById('framePage')
11.	            console.log(framePage.contentWindow.document.body) //同源的可以获取,非同源的无法获取
12.	        }
13.	    </script>
14.	</body>

获取DOM

获取不到

2. 第二个限制,源a不能访问源b的cookie

3.	<!DOCTYPE html>
4.	<html lang="en">
5.	
6.	<head>
7.	    <meta charset="UTF-8">
8.	    <meta name="viewport" content="width=device-width, initial-scale=1.0">
9.	    <title>Document</title>
10.	</head>
11.	
12.	<body>
13.	    <h1>我是页面1</h1>
14.	    <button onclick="getCookie()">获取页面2的cookie</button>
15.	    <br>
16.	    <!-- <iframe id="framePage" src="./demo.html"></iframe> -->
17.	    <iframe id="framePage" src="https://www.bilibili.com"></iframe>
18.	
19.	    <script type="text/javascript">
20.	        function getCookie() {
21.	            const framePage = document.getElementById('framePage')
22.	            console.log(framePage.contentWindow.document.cookie) //同源的可以获取,非同源的无法获取
23.	        }
24.	    </script>
25.	</body>
26.	
27.	</html>

还是一样的页面,这次获取的是cookie

也是获取不到的,因为你在获取document这一步就已经失败了

3. ajax响应数据限制:源a可以给源b发请求,但是无法获取源b响应的数据。

这是一个获取头条新闻的页面

代码

28.	<!DOCTYPE html>
29.	<html lang="en">
30.	<head>
31.	    <meta charset="UTF-8">
32.	    <meta name="viewport" content="width=device-width, initial-scale=1.0">
33.	    <title>Document</title>
34.	</head>
35.	<body>
36.	    <button onclick="getNews()">获取头条新闻</button>
37.	
38.	    <script>
39.	        async function getNews() {
40.	            const result = await fetch('https://www.toutiao.com/hot-event/hot-board/?origin=toutiao_pc');
41.	            const data = await result.json();
42.	            console.log('data');
43.	        }
44.	    </script>
45.	</body>
46.	</html>

页面

获取不到

备注:在上述限制中,浏览器对 Ajax 获取数据的限制是影响最大的一个,且实际开发中经常遇到。

几个注意点

  1. 跨域限制仅存在浏览器端,服务端不存在跨域。
  2. 即使跨域了,ajax请求也可以正常发出,但响应数据不会交给开发者。
  3. link,script,img这些标签发出的请求也可能跨域,只不过浏览器对标签跨域不做严格限制,对开发几乎无影响。

那么要如何解决跨域

想要解决跨域,一般有三种方法

第一种,用CORS解决ajax跨域问题

CORS 概述

CORS 全称:Cross-Origin Resource Sharing(跨域资源共享),是用于控制浏览器校验跨域请求的一套规范,服务器依照 CORS 规范,添加特定响应头来控制浏览器校验,大致规则如下:

  • 服务器明确表示拒绝跨域请求,或没有表示,则浏览器校验不通过
  • 服务器明确表示允许跨域请求,则浏览器校验通过

了解了CORS之后,还要了解一下简单请求和复杂请求

CORS 会把请求分为两类,分别是:1.简单请求、2.复杂请求。

简单请求要满足这个三个条件

  1. 请求方法要为 get, head或者post。
  2. 请求头字段要符合CORS安全规范(https://fetch.spec.whatwg.org/#cors-safelisted-request-header), 一般只要不手动修改请求头,都能符合改规范。
  3. 请求头的Content-Type的值只能是这三种:

text/plain

multipart/form-data

application/x-www-form-urlencoded

不满足这三个要求的请求都是复杂请求,而复杂请求会自动发送预检请求

预检请求是一种在实际跨域请求发出之前,由浏览器自动发出的一种请求。主要用于向服务器确认是否允许接下来的跨域请求。基本流程是这样的,浏览器先发起一个options请求,携带这个几个请求头,Origin(发起请求的源),Access-Control-Request-Method(实际请求的HTTP方法),Access-Control-Request-Headers(实际请求中使用的自定义头)。如果通过预检,才会继续发起实际的跨域请求。

这就是预检请求

CORS 解决简单请求跨域

前端

1.	<!DOCTYPE html>
2.	<html lang="en">
3.	<head>
4.	    <meta charset="UTF-8">
5.	    <meta name="viewport" content="width=device-width, initial-scale=1.0">
6.	    <title>Document</title>
7.	</head>
8.	<body>
9.	    <button onclick="getData()">获取数据</button>
10.	
11.	    <script>
12.	        async function getData() {
13.	            const url = 'http://127.0.0.1:8081/';
14.	            const result = await fetch(url);
15.	            const data = await result.json();
16.	            console.log('data');
17.	        }
18.	    </script>
19.	</body>
20.	</html>

服务端代码(以express框架为例):

1.	const express = require('express');
2.	const app = express();
3.	
4.	app.get('/', (req, res) => {
5.	    res.send([{ name: '张三', age: 19 }])
6.	})
7.	
8.	app.listen(8081, () => {
9.	    console.log('服务器成功启动');
10.	})

这个时候是获取不到数据的

设置下cors

1.	const express = require('express');
2.	const app = express();
3.	
4.	app.get('/', (req, res) => {
5.	    res.setHeader('Access-Control-Allow-Origin','http://127.0.0.1:5500')
6.	    res.send([{ name: '张三', age: 19 }])
7.	})
8.	
9.	app.listen(8081, () => {
10.	    console.log('服务器成功启动');
11.	})

这样就能获取到数据了

整体思路:服务器在给出响应时,通过添加Access-Control-Allow-Origin响应头,来明确表达允许某个源发起跨域请求,随后浏览器在校验时,直接通过。

像这样的设置是允许某个源跨域

1.	// 允许 http://127.0.0.1:5500 这个源发起跨域请求
2.	res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:5500')

而这样则是允许所有源跨域

1.	// 允许所有源发起跨域请求
2.	res.setHeader('Access-Control-Allow-Origin', '*')

CORS 解决复杂请求跨域

第一步:服务器先通过浏览器的预检请求,服务器需要返回如下响应头

Access-Control-Allow-Origin(允许的源)

Access-Control-Allow-Methods(允许的方法)

Access-Control-Allow-Headers(允许的自定义头)

Access-Control-Max-Age(预检请求的结果缓存时间(可选))

第二步:处理实际的跨域请求(与处理简单请求跨域的方式相同)

服务器代码

1.	const express = require('express');
2.	const app = express();
3.	
4.	app.options('/', (req, res) => {
5.	    res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:5500')
6.	    res.setHeader('Access-Control-Allow-Methods', 'GET')
7.	    res.setHeader('Access-Control-Allow-Headers', 'city')
8.	    res.send()
9.	})
10.	
11.	app.get('/', (req, res) => {
12.	    res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:5500')
13.	    res.send([{ name: '张三', age: 19 }])
14.	})
15.	
16.	app.listen(8081, () => {
17.	    console.log('服务器成功启动');
18.	})

前端代码

1.	<!DOCTYPE html>
2.	<html lang="en">
3.	<head>
4.	    <meta charset="UTF-8">
5.	    <meta name="viewport" content="width=device-width, initial-scale=1.0">
6.	    <title>Document</title>
7.	</head>
8.	<body>
9.	    <button onclick="getData()">获取数据</button>
10.	
11.	    <script>
12.	        async function getData() {
13.	            const url = 'http://127.0.0.1:8081/';
14.	            const result = await fetch(url, { method: 'GET', headers: { city: 'beijing' } });
15.	            const data = await result.json();
16.	            console.log('data', data);
17.	        }
18.	    </script>
19.	</body>
20.	</html>

数据获取到了

预检请求返回的响应头

借助 cors 库快速完成配置

上述的配置中需要自己配置响应头,比较麻烦,借助cors库,可以更方便完成配置

安装cors

npm i cors

配置cors

1.	const express = require('express');
2.	const cors = require('cors');
3.	const app = express();
4.	
5.	// 使用cors中间件
6.	app.use(cors({
7.	    origin: 'http://127.0.0.1:5500', // 允许的源
8.	    methods: ['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS'], // 允许的方法
9.	    allowedHeaders: ['city'], // 允许的自定义头
10.	    exposedHeaders: ['abc'], // 要暴露的响应头
11.	    optionsSuccessStatus: 200 // 预检请求成功的状态码
12.	}))
13.	
14.	app.get('/', (req, res) => {
15.	    res.setHeader('abc', '123')
16.	    res.send([{ name: '张三', age: 19 }])
17.	})
18.	
19.	app.listen(8081, () => {
20.	    console.log('服务器成功启动');
21.	})
22.	

成功获取数据

第二种,JSONP 解决跨域问题

JSONP 概述: JSONP 是利用了<script>标签可以跨域加载脚本,且不受严格限制的特性,可以说是程序员智慧的结晶,早期一些浏览器不支持 CORS 的时,可以靠 JSONP 解决跨域(现在基本不用了)。

基本流程:

    • 第一步:客户端创建一个<script>标签,并将其src属性设置为包含跨域请求的 URL,同时准备一个回调函数,这个回调函数用于处理返回的数据。
    • 第二步:服务端接收到请求后,将数据封装在回调函数中并返回。
    • 第三步:客户端的回调函数被调用,数据以参数的形势传入回调函数。

示例代码

前端

1.	<!DOCTYPE html>
2.	<html lang="en">
3.	<head>
4.	    <meta charset="UTF-8">
5.	    <meta name="viewport" content="width=device-width, initial-scale=1.0">
6.	    <title>Document</title>
7.	</head>
8.	<body>
9.	    <script>
10.	        function callback(data) {
11.	            console.log('data', data)
12.	        }
13.	    </script>
14.	    <script src="http://127.0.0.1:8081/users"></script>
15.	</body>
16.	</html>

后端

1.	const express = require('express');
2.	const app = express();
3.	
4.	app.get('/users', (req, res) => {
5.	    res.send(`callback([{ name: '张三', age: 19 }])`)
6.	})
7.	
8.	app.listen(8081, () => {
9.	    console.log('服务器成功启动');
10.	})

结果

优化下代码

前端

1.	<!DOCTYPE html>
2.	<html lang="en">
3.	
4.	<head>
5.	    <meta charset="UTF-8">
6.	    <meta name="viewport" content="width=device-width, initial-scale=1.0">
7.	    <title>Document</title>
8.	</head>
9.	
10.	<body>
11.	    <button onclick="getUsers()">获取用户</button>
12.	
13.	    <script>
14.	        function test(data) {
15.	            console.log('data', data)
16.	        }
17.	        function getUsers() {
18.	            // 创建script元素
19.	            const script = document.createElement('script')
20.	            // 指定script的src属性
21.	            script.src = 'http://127.0.0.1:8081/users?callback=test'
22.	            // 将script元素添加到body中触发脚本加载
23.	            document.body.appendChild(script)
24.	            // script标签加载完毕后移除该标签
25.	            script.onload = () => {
26.	                script.remove()
27.	            }
28.	        }
29.	    </script>
30.	</body>
31.	
32.	</html>

后端

1.	const express = require('express');
2.	const app = express();
3.	
4.	const users = [
5.	    { name: '张三', age: 19 },
6.	    { name: '李四', age: 20 }
7.	]
8.	
9.	app.get('/users', (req, res) => {
10.	    const { callback } = req.query
11.	    res.send(`${callback}(${JSON.stringify(users)})`)
12.	})
13.	
14.	app.listen(8081, () => {
15.	    console.log('服务器成功启动');
16.	})

效果

用jQuery封装jsonp

1.	$.getJSON('http://127.0.0.1:8081/teachers?callback=?', (data) => {
2.	            console.log(data)
3.	        })

第三种,配置代理服务器解决跨域

这里需要用到http-proxy-middleware这个包来配置代理服务器

下载http-proxy-middleware

npm i http-proxy-middleware

前端

1.	<!DOCTYPE html>
2.	<html lang="en">
3.	<head>
4.	    <meta charset="UTF-8">
5.	    <meta name="viewport" content="width=device-width, initial-scale=1.0">
6.	    <title>Document</title>
7.	</head>
8.	<body>
9.	    <button onclick="getNews()">获取头条数据</button>
10.	
11.	    <script>
12.	        async function getNews() {
13.	            const url = 'http://127.0.0.1:8081/api/hot-event/hot-board/?origin=toutiao_pc';
14.	            const result = await fetch(url);
15.	            const data = result.json();
16.	            console.log('data', data);
17.	        }
18.	    </script>
19.	</body>
20.	</html>

后端

1.	const express = require('express');
2.	const app = express();
3.	const { createProxyMiddleware } = require('http-proxy-middleware');
4.	
5.	app.use(express.static('./public'))
6.	
7.	app.use('/api', createProxyMiddleware({ // 拦截所有带有/api的请求
8.	    target:'https://www.toutiao.com', // 转发的目标
9.	    changeOrigin:true, // 允许跨域
10.	    pathRewrite:{
11.	      '^/api':'' // 把路径中的/api去掉
12.	    }
13.	  }))
14.	
15.	app.listen(8081, () => {
16.	    console.log('服务器成功启动');
17.	})
18.	

需要把前端代码当成静态资源部署在服务器上

目录

把服务器启动了,需要去http://127.0.0.1:8081获取页面

点击获取数据

数据成功获取

相关文章:

Angular由一个bug说起之十三:Cross Origin

跨域 想要了解跨域&#xff0c;首要要了解源 什么是源&#xff0c;源等于协议加域名加端口号 只有这三个都相同&#xff0c;才是同源&#xff0c;反之则是非同源。 比如下面这四个里&#xff0c;只有第4个是同源 而浏览器给服务器发送请求时&#xff0c;他们的源一样&#xff0…...

WEB前端-2

目录 HTML-常见的网页标签-分类2 语义化标签 列表标签 表单标签 form标签 input标签 select标签 textarea标签 html转义符 h5提供的新标签 【例3&#xff1a;豆瓣电影】 【源码】 【例4&#xff1a;登录注册】 【源码】 【例5&#xff1a;QQ注册】 【源码】 H…...

高斯混合模型 (Gaussian Mixture Model, GMM) 算法详解与PyTorch实现

高斯混合模型 (Gaussian Mixture Model, GMM) 算法详解与PyTorch实现 目录 高斯混合模型 (Gaussian Mixture Model, GMM) 算法详解与PyTorch实现1. 高斯混合模型 (GMM) 算法概述1.1 高斯分布1.2 GMM的优势2. GMM的核心技术2.1 模型定义2.2 参数估计2.3 损失函数3. PyTorch实现G…...

web作业

作业一 <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0"> <title>Document</title> </head&g…...

Tauri教程-基础篇-第一节 Tauri项目创建及结构说明

“如果结果不如你所愿&#xff0c;就在尘埃落定前奋力一搏。”——《夏目友人帐》 “有些事不是看到了希望才去坚持&#xff0c;而是因为坚持才会看到希望。”——《十宗罪》 “维持现状意味着空耗你的努力和生命。”——纪伯伦 Tauri 技术教程 * 第四章 Tauri的基础教程 第一节…...

计算机网络之---物理层标准与协议

常见的物理层标准 1. IEEE 802 标准 IEEE 802 是一系列定义局域网和城域网通信协议的标准&#xff0c;其中许多标准涉及到物理层的技术细节&#xff1a; IEEE 802.3 (Ethernet)&#xff1a;定义了以太网的物理层规范&#xff0c;规定了如何通过电缆&#xff08;例如同轴电缆…...

Idea日志乱码

问题描述 前提&#xff1a;本人使用windows Idea运行sh文件&#xff0c;指定了utf-8编码&#xff0c;但是运行过程中还是存在中文乱码 Idea的相关配置都已经调整 字体调整为雅黑 文件编码均调整为UTF-8 调整Idea配置文件 但是还是存在乱码&#xff0c;既然Idea相关配置已经…...

tk GMV MAX素材范围投放指南

Product GMy Max素材范围说明 Product GMy Max能自动获取带有相关商品锚点链接&#xff08;无论是单个锚点还是多个锚点&#xff09;的视频&#xff0c;并将其用于推广特定商品的广告素材&#xff0c;前提是这些视频已经获得广告授权。然而&#xff0c;请注意&#xff0c;多个…...

TANGO - 数字人全身动作生成

文章目录 一、关于 TANGO演示视频&#xff08;YouTube&#xff09;&#x1f4dd;发布计划 二、⚒️安装克隆存储库构建环境 三、&#x1f680;训练和推理1、推理2、为自定义字符创建图形 一、关于 TANGO TANGO 是 具有分层音频运动嵌入 和 扩散插值的共语音手势视频再现 由东…...

springboot集成整合工作流,activiti审批流,整合实际案例,流程图设计,流程自定义,表单配置自定义,代码demo流程

前言 activiti工作流引擎项目&#xff0c;企业erp、oa、hr、crm等企事业办公系统轻松落地&#xff0c;一套完整并且实际运用在多套项目中的案例&#xff0c;满足日常业务流程审批需求。 一、项目形式 springbootvueactiviti集成了activiti在线编辑器&#xff0c;流行的前后端…...

Windows 10 ARM工控主板连接I2S音频芯片

在Windows工控主板应用中&#xff0c;音频功能是一项基本的需求&#xff0c;USB声卡在x86/x64 Windows系统上就可直接免驱使用&#xff0c;但这些USB声卡通常不提供ARM上的Windows系统驱动。本文将介绍如何利用安装在ARM上的Windows工控主板——ESM8400的I2S接口、连接WM8960音…...

单元测试MockitoExtension和SpringExtension

1. MockitoExtension MockitoExtension 是 JUnit 5 提供的一个扩展&#xff0c;用于支持 Mockito 的集成。它可以自动初始化标记为 Mock、InjectMocks 等的 Mockito 对象&#xff0c;而不需要显式调用 MockitoAnnotations.initMocks(this)。 主要特点: 自动初始化 Mock、Spy…...

网络安全 | WAF防护开通流程与技术原理详解

关注&#xff1a;CodingTechWork 引言 随着互联网安全形势的日益严峻&#xff0c;Web应用防火墙&#xff08;WAF, Web Application Firewall&#xff09;逐渐成为网站和应用的标准防护措施。WAF能够有效识别和防止如SQL注入、跨站脚本攻击&#xff08;XSS&#xff09;、恶意流…...

模型 断裂点理论(风险控制)

系列文章 分享模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。设置小损失&#xff0c;防止大风险。 1 断裂点理论的应用 1.1 电路系统中的保险丝应用 背景介绍&#xff1a; 在工程学中&#xff0c;电路系统是现代科技中不可或缺的一部分&#xff0c;广泛应用于各…...

02.MPLS动态LSP配置实验

MPLS动态LSP配置实验 MPLS动态LSP配置实验基本配置MPLS部分查看LDP会话基本信息查看详细信息查看MPLS动态LSP配置实验 基本配置 接口地址和OSPF配置,省略!全网互通! 注意:8.8.8.8和9.9.9.9也要宣告! MPLS部分 [ar1]mpls lsr-id 1.1.1.1 [ar1]mpls Info: Mpls starting,…...

MySQL 中的Buffer Pool

深入解析 MySQL Buffer Pool&#xff1a;优化数据库性能的核心 引言 在关系型数据库管理系统&#xff08;RDBMS&#xff09;中&#xff0c;磁盘I/O通常是性能瓶颈之一。为了缓解这个问题&#xff0c;MySQL的InnoDB存储引擎引入了Buffer Pool这一概念。Buffer Pool作为内存中的…...

修复微pe系统uefi引导损坏windows failed to start...

打开微pe,点右下角生成iso镜像 再打开iso镜像,把里面所有文件复制到微pe启动盘的EFI分区(使用diskgenius才能看到该分区) 虚拟机启动测试...

【Vue3中使用crypto-js】crypto-js加密解密用法

目录 1、安装crypto2、创建crypto.js文件3、在main.js主文件中进行引用4、页面中进行使用5、实现效果展示6、加密模式解析以及iv参数使用 1、安装crypto npm install crypto-js 如果是在Typescript版本需要再安装 npm install --save types/crypto-js2、创建crypto.js文件 注…...

JavaWeb开发(九)JSP技术

1. JavaWeb JSP技术 1.1. JSP简介 1.1.1. 什么是JSP JSP全名为Java Server Page 是为了简化servlet的工作而出现的替代品。在JSP中java代码与HTML共同存在&#xff0c;其中HTML代码用于展示静态的内容&#xff0c;java代码用来展示动态的内容。 1.1.2. 为什么出现JSP技术 19…...

PADS Lyout布局布线实战技巧:布线优化及解决碎铜问题

1、通过加过孔 通过过孔复制 复制粘贴 也可以选择网络&#xff0c;选择右键&#xff0c;添加过孔来。 在一些孤铜的地方加过孔&#xff0c;加不了过孔的情况下&#xff0c;怎么办&#xff1f; 2、通过挖掉&#xff0c;不让铜在孤零零的地方。 右键&#xff0c;选择矩形&a…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

腾讯云V3签名

想要接入腾讯云的Api&#xff0c;必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口&#xff0c;但总是卡在签名这一步&#xff0c;最后放弃选择SDK&#xff0c;这次终于自己代码实现。 可能腾讯云翻新了接口文档&#xff0c;现在阅读起来&#xff0c;清晰了很多&…...

C语言中提供的第三方库之哈希表实现

一. 简介 前面一篇文章简单学习了C语言中第三方库&#xff08;uthash库&#xff09;提供对哈希表的操作&#xff0c;文章如下&#xff1a; C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...

Rust 开发环境搭建

环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行&#xff1a; rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu ​ 2、Hello World fn main() { println…...

OD 算法题 B卷【正整数到Excel编号之间的转换】

文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的&#xff1a;a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...

结构化文件管理实战:实现目录自动创建与归类

手动操作容易因疲劳或疏忽导致命名错误、路径混乱等问题&#xff0c;进而引发后续程序异常。使用工具进行标准化操作&#xff0c;能有效降低出错概率。 需要快速整理大量文件的技术用户而言&#xff0c;这款工具提供了一种轻便高效的解决方案。程序体积仅有 156KB&#xff0c;…...

LangChain【6】之输出解析器:结构化LLM响应的关键工具

文章目录 一 LangChain输出解析器概述1.1 什么是输出解析器&#xff1f;1.2 主要功能与工作原理1.3 常用解析器类型 二 主要输出解析器类型2.1 Pydantic/Json输出解析器2.2 结构化输出解析器2.3 列表解析器2.4 日期解析器2.5 Json输出解析器2.6 xml输出解析器 三 高级使用技巧3…...

break 语句和 continue 语句

break语句和continue语句都具有跳转作用&#xff0c;可以让代码不按既有的顺序执行 break break语句用于跳出代码块或循环 1 2 3 4 5 6 for (var i 0; i < 5; i) { if (i 3){ break; } console.log(i); } continue continue语句用于立即终…...

使用 uv 工具快速部署并管理 vLLM 推理环境

uv&#xff1a;现代 Python 项目管理的高效助手 uv&#xff1a;Rust 驱动的 Python 包管理新时代 在部署大语言模型&#xff08;LLM&#xff09;推理服务时&#xff0c;vLLM 是一个备受关注的方案&#xff0c;具备高吞吐、低延迟和对 OpenAI API 的良好兼容性。为了提高部署效…...