1.HTTP面试题
1.HTTP基本概念
1.1 HTTP是什么
HTTP(HyperText Transfer Protocol)是超文本传输协议。它是一种双向传输协议。具体来说HTTP是一种在计算机世界里,专门在[两点]之间[传输]文字、图片、音频、视频等[超文本]数据的[约定和规范]。
1.2 HTTP常见状态码有哪些
1XX类状态码属于提示信息,是协议处理中的一种中间状态;
2XX类状态码表示服务器成功处理了客户端的请求;
- [200 OK]是最常见的成功状态码,表示一切正常。如果非HEAD请求,服务器返回的响应头都会有body数据;
- [204 NoContent]也是最常见的成功状态码,与200 OK基本相同,但响应头没有body数据;
- [206 partical Content]应用于HTTP分块下载或断点续传,表示响应返回的body数据并不是资源的全部,而是其中一部分,也是服务器处理成功的状态。
3XX类状态码表示客户端请求的资源发生了变动,需要客户端用新的URL重新发送请求获取资源,即重定向。
- [301 Moved Permantly]表示永久重定向,说明请求的资源已经不存在,需改用新的URL再次访问;
- [302 Found]表示临时重定向,说明请求的资源还在,但是暂时需要用另一个URL访问该资源;
- [304 Not Modified]表示资源未修改,重定向到已存在的缓存文件,即缓存重定向。告诉客户端可以继续使用缓存资源,用于缓存控制。
4XX类状态码表示客户端发送的报文有误,服务端无法处理,即客户端错误
- [400 Bad Request]表示客户端请求的报文有误;
- [403 Forbidden]表示服务器的资源禁止访问,或客户端无权访问,并不是客户端请求出错;
- [404 Not Found]表示客户端请求的资源在服务端不存在或找不到,所以无法提供给客户端。
5XX类状态码表示客户端请求报文正确,但服务器处理时内部发生错误,属于服务端错误。
- [500 Internal Server Error]与400类似,笼统通用的错误码;
- [501 Not Imaplmwented]表示客户端请求的功能服务端暂时不支持,类似“即将开业,敬请期待”;
- [502 Bad Gateway]通常是服务端作为网关或代理时返回的错误码,表示服务器自身工作正常,访问后端服务器发生错误;
- [503 Service Unavailable]表示服务器正忙,暂时无法响应客户端,类似“网络服务正忙,请稍后重试”。
1.3 HTTP常见字段有哪些
- Host字段:用于请求发送到同一台服务器的不同程序;
- Content-Length:服务器返回数据的数据长度。HTTP协议通过设置回车符、换行符作为HTTP header边界,通过Content-Length字段作为Http Body边界,解决“粘包”问题。
- Connection字段:(Connection=keep-alive)表示用户端与服务端使用HTTP长连接机制,只要任意一端没有明确断开连接,则保持TCP连接状态;
- Content-Type(Content-Type=text/html;charset=utf-8):用于响应客户端,告诉其本次数据什么格式;客户端Accept:*/*表示接收任何数据格式;
- Content-Encoding字段(Content-Encoding:gzip)表示服务端返回数据使用的压缩方法;客户端的Accept-Encoding=gzip,deflate表示接收这两种压缩方式。
2.GET与POST
2.1 Get和Post区别
RFC(Request For Comment):互联网工程任务组(IETTF)发布的用于标准化互联网协议和技术的文件。该文件包含协议规范、安全、路由、传输控制、网络管理等相关信息,该文档是互联网工程和网络技术领域的权威性和可信度文档。
- 根据RFC规范,Get是从服务其获取指定的(静态文本、页面、图片、音视频)资源。Get请求参数写在支持ASCLL字符且长度有限制的URL中。
- 根据RFC规范,Post是请求负荷(任意类型和大小的报文body)对指定的(静态文本、页面、图片、音视频)资源作出处理。
关于Get和Post方法请求流程这里贴上xiaolincoding的图片
2.2 Get和Post方法都是安全和幂等的吗
在HTTP协议中,安全是指请求方法不会破坏服务器上的资源;幂等是指多次执行相同的操作,结果都是相同的。
- 根据RFC规范,Get方法时安全且幂等的,可以对Get请求的数据做缓存,缓存在浏览器本身(减少浏览器重复请求相同资源),也可以用于代理(如Nginx),浏览器的Get请求可保存为书签;
- 根据RFC规范,Post方法不是安全幂等的,浏览器一般不会缓存Post请求,也不能将其保存为书签。
RFC中并没有规定Get不能带body,理论上任何请求都可以带有body;URL查询参数并不是Get独有,Post请求的URL也可以带有参数。
3.HTTP特性
3.1 Http/1.1优点
- 简单:头部信息键值对是简单文本形式,基本报文格式:header+body;
- 灵活易于扩展:协议中的请求方法、URI/URL、状态码、头字段可以由开发人员自定义和扩展。在HTTP下层传输协议中,HTTPS在HTTP与TCP之间增加了SST/TLS安全传输层;HTTP/1.1和HTTP/2.0传输协议使用的TCP协议,HTTP/3.0协议使用的UDP协议;
- 应用广泛、跨平台:无论是电脑还是
3.2 Http/1.1缺点
- 无状态双刃剑:不额外使用资源记录状态信息,减轻服务器负担;每次操作都需要验证用户身份,用户体验感差。我们可以将请求和响应报文写入Coolie信息控制客户端状态。流程r如下图:
- 明文传输双刃剑:方便阅读但是无隐私可言
- 不安全:
1)内容被窃取:找好信息泄漏,号没了;
2)不验证通行身份,遭遇伪装,访问淘宝,拼多多,钱没了;
3)无法验证报文完整性,可能被篡改:网页植入垃圾广告,视觉污染,眼没了
HTTP的安全问题可以通过在HTTPS协议在HTTP和TCP协议中间添加SSL和TLS协议增加安全性。
3.3 Http/1.1性能
HTTP协议基于TCP/IP协议,使用[请求--回应]通信模式;
- 长连接:减少TCP重新建立和断开的额外开销,减轻服务器负担。只要任意一端没有明确提出断开连接,TCP保持连接状态。如果某个HTTP连接超过一定时间没有任何数据交互,服务器会主动断开该连接。
- 管道网络传输:同一个TCP连接中,客户端可以发起多个请求,只要第一个请求发送出去,不必等待其响应,就可以发送第二个请求,减少整体响应时间。但是服务器必须按照管道的请求顺序响应请求。HTTP/1.1解决了请求的对头阻塞,但是没有解决响应的对头阻塞。
- 队头阻塞:如果顺序发送的请求序列中一个请求因为某种原因被阻塞,后面排队的所有请求一同被阻塞,导致客户端一直请求不到数据。
4.HTTP缓存技术
为避免重读的Http请求发送,可以将[请求-响应]的数据缓存在本地,因此Http头部中有很多针对缓存的字段。Http缓存技术有两种:强制缓存,协商缓存。
4.1 强制缓存
强制缓存是指浏览器如果判断缓存没有过期,则直接使用浏览器的本地缓存,使用缓存的主动性在浏览器这边。如下图,返回200状态码表示数据返回成功,在其后续括号中标识了from disk cache,这标识了使用强制缓存。
强制缓存通过HTTP响应头部的Cache-Control(相对时间)字段和Expires(绝对时间)字段实现,表示资源在客户端浏览器缓存的有效期。如果同时又Cache-Control和Expires字段,Cache-Control优先级更高。
Cache资源选项更多,设置更详细,建议使用Cache-Control实现强制缓存,工作流程如下:
- 当浏览器第一次访问服务器资源时,服务器在返回该资源的同时,在Response头部加上Cache-Control,并在Cache-Control中设置过期时间;
- 浏览器再次请求访问服务器中的该资源时,先通过请求资源的时间与Cache-Control中设置的过期时间大小计算比较资源是否过期,没过期就是用缓存,过期就重新请求服务器;
- 服务器再次收到请求后,会再次更新Response头部的Cache-Control。
4.2 协商缓存
协商缓存是指服务端通过状态码304告诉客户端可以使用缓存的资源。
协商缓存过程:与服务器协商之后,通过协商结果判断是否使用本地缓存。
协商缓存通过两种头部实现:
第一种:请求头部中的if-Modified-Since字段与响应头部中的Last-Modified字段实现
- 响应头部中的Last-Modified:标识响应资源的最后修改时间
- 请求头部中的If-Modified-Since:当资源过期,如果响应头部中具有Last-Modified声明,则再次发起请求的时候带上Last-Modified;服务器收到请求后比较If-Modified-Since和Last-Modified时间,若Last-Modified时间大,则资源被修改过,服务器返回新资源,HTTP 200 OK;如果if-Modified-Since时间大,说明资源没有被修改过,响应HTTP 304走本地缓存获取资源。
第二种:请求头部中的if-None-Match字段和响应头部中的Etag字段
- 响应头部的Etag:唯一标识响应资源;
- 请求头部中的if-None-Match:当资源过期时,浏览器发现响应头里有Etag,则再次向服务器发起请求时,会将请求头中的If-None-Match设置为Etag的值。服务器收到请求后进行对比,如果资源没有变化返回304,如果资源变化重新请求服务器返回200。
两者比较:
第一种请求头部的If-Modified-Since和响应头部的Last-Modfied是基于时间的,第二种请求头部If-None-Match和响应头部的Etag是基于唯一标识的,相对来说后者能够更加准确地判断文件内容是否被修改,避免由于时间篡改导致不可靠问题。
第一次请求服务器资源时,服务器返回的HTTP响应头部同时由Etag和Last-Modified字段。客户端再次请求的时候,会带上这两个字段访问服务器,这时Etag优先级更高,服务器会先判断Etag是否变化,如果有变化不再判断Last-Modified,如果有变化再烂Last-Modified。
ETag现规定与Last-Modified优点:
- 在没有修改改动情况下,Last-Modified可能改变,导致客户端认为文件改动,重新请求服务器;
- 可能有些文件是在秒级以内修改,而If-Modified-Since检查到的粒度是秒级,使用Etag能够保证在这种需求下客户端在一秒内刷新多次;
- 有些服务器不能精准获取文件最后修改时间。
注意:协商缓存中请求和响应中的两个字段需要配合Cache-Control字段使用,只有在没有命中强制缓存的情况下,才能发起带有协商缓存的字段请求。总体缓存流程图如下:
使用Etag字段实现协商缓存过程:
-
当浏览器第一次请求服务器资源时,服务器在返回资源的同时,在其Response头部加上Etag唯一标识,这个标识值是根据当前请求的资源生成的;
-
当浏览器再次请求服务器的资源时,首先会检查强制缓存是否过期:
-
如果没有过期,直接使用本地缓存;
-
如果缓存过期,会在Request拖布加上If-None-Match字段,该字段值就是Etag唯一标识
-
-
服务器再次收到请求后,会根据请求的If-None-Match值与当前请求的资源生成的唯一标识进行比较:
-
如果值相等,则返回304 Not Modified,不会返回资源;
-
如果值不相等,则会返回200状态码和请求资源,并在Respons头部加上新的Etag唯一标识
-
-
如果浏览器收到304请求响应状态码,则从本地缓存中加载资源,否则更新资源。
5.HTTP与HTTPS
5.1 HTTP与HTTPS的区别
- HTTP是超文本明文传输协议,不安全,HTTPS在HTTP和TCP之间增加了SSL(Secure Socket Layer)/TLS(Transport Layer Security)安全协议,使报文能顾安全传输。
- HTTP只需要TCP三次握手就能建立连接,HTTPS在TCP三次握手后还需要进行SSL/TLS握手才能进入加密报文传输;
- 两者默认端口不同,HTTP默认端口是80,HTTPS默认端口是443;
- HTTPS协议需要向CA(证书权威结构)申请数字证书,保证服务器的身份是可信的。
5.2 HTTPS解决了HTTP哪些问题
由于HTTP是明文传输,安全上UC能在以下三个问题:
- 窃听风险:通信链路上可获取通信内容,用户账号没了;
- 冒充风险:冒充淘宝网站,钱没了;
- 篡改风险,强制植入垃圾广告,眼没了
HTTPS在HTTP与TCP之间增加了SSL/TLS协议,解决上述风险:
- 信息加密:交互信息无法被窃取,但账号会因[自身忘记]而没;
- 校验机制:无法篡改通信信息,
-
-
摘要算法(哈希函数)实现交互信息的完整性,为数据生成独一无二的[指纹],校验数据完整性,解决篡改风险;
-
服务器公钥放入数字证书
5.2.1 混合机加密
HTTPS通过混合加密保证信息的机密性,解决窃听风险
HTTPS采用对称加密和非对称加密实现混合加密
- 通信建立前使用非对称加密交换[会话秘钥],后续不再使用非对称加密;
- 通信过程中使用对称加密的[会话秘钥]方式加密明文数据。
采用[混合加密]方式原因:
- 对称加密只使用一个密钥,运算速度快,密钥需要保密,无法做到安全的密钥交换;
- 非对称加密使用两个密钥,公钥和私钥,公钥可任意分发尔斯要保密,解决密钥交换安全问题,但计算速度慢。
5.2.2 摘要算法+数字签名
为保证传输内容不被篡改,发送方使用摘要算法(哈希函数)计算出传输内容的哈希值(即指纹,由于哈希值唯一,因此无法通过哈希值推导出传输内容),然后同内容一起发送给接收方。接收方收到哈希加密的内容后,也使用哈希算法计算传输内容的哈希值,然后将接收到的哈希值与自己计算出的哈希值比较。如果相等则内容没有被篡改;反之,则被篡改。
哈希算法只能确保内容不被篡改,但是存在[内容+哈希值]被中间人替换的问题,因为需要证明客户端接受的消息来源于服务端。因此,计算机使用非对称加密算法(公钥(公开给所有人)和私钥(本人保存))对[内容和哈希值]进行双向加密。双向加密分为公钥加密,私钥解密;私钥加密,公钥解密。加密流程不同,功能也不同.
- 公钥加密,私钥解密:保证内容传输安全。公钥加密后内容,只有私钥持有者才能解密出实际内容;
- 私钥加密,公钥解密:保证消息不会被冒充。私钥不外泄,公钥正常解密私钥加密内容,证明消息由私钥持有者发送。
5.2.3 数字证书
哈希算法能够保证消息的完整性,数字签名能够保证消息的可靠性,但还是缺少身份的验证(若公钥被伪造)。计算机中有一个权威机构CA(数字证书认证机构),它将服务器公钥放于数字证书中(由数字证书权威机构颁发),只要证书可信,公钥就可信。
通过数字证书保证服务器公钥身份,解决冒充风险。
5.3 HTTPS如何建立连接,期间交换了什么
SSL/TLS协议基本流程:
- 客户端向服务器索要并验证服务器的公钥;
- 双方协议产生[会话秘钥];
- 双方采用[会话秘钥]进行加密通信;
前两步是SST/TLS建立过程,即TLS握手阶段。TLS的[握手阶段]涉及四次通信,使用不同的秘钥交换算法,TLS握手流程也不相同,常用秘钥交换算法由:RSA算法和ECDE算法。
基于RSA算法的TLS握手较容易,握手过程如下:
5.3.1 TLS协议建立详细流程:
1.ClientHello
首先,客户端向服务端发起加密通信请求,即ClientHello请求。
这一步,客户端向服务器发送以下信息:
-
客户端支持的TLS协议版本,如TLS1.2版本;
-
客户端生产的随机数(Client Random),后面用于生成[会话秘钥]条件之一;
-
客户端支持的密码套件列表,如RSA加密算法。
2.ServerHello
服务器收到客户端请求后,向客户端发出响应,即ServerHello。服务器回应内容如下:
-
确认TLS版本,如果浏览器不支持,则关闭加密通信;
-
服务器生产随机数(Server Random),用于后面生产[会话秘钥]条件之一;
-
确认的密码套件列表,如RSA加密算法;
-
服务器的数字证书
3.客户端回应
客户端收到服务器的回应后,首先通过浏览器或操作系统中的CA公钥,确认服务器的数字证书的真实性。
如果证书没有问题,客户端会从数字证书中取出服务器的公钥,然后使用它加密报文,向服务器发送如下消息:
-
一个随机数(pre-master-key),该随机数字被服务器公钥加密;
-
加密通信算法改变通知,表示随后信息都将用[会话秘钥]加密通信;
-
客户端握手结束通知,表示客户端的握手阶段结束。同时将之前所有改变的内容数据做个摘要,用于供服务端校验。
上面第一项的随机数是整个握手阶段的第三个随机数,会发给服务端,该随机数客户端和服务端是相同的。
服务端和客户端有这三个随机数(Client Random、ServerRandom、pre-master-key),接着使用双方协议的加密算法,各自生成本次通信的[会话秘钥]。
4.服务器的最后回应
服务端收到客户端的第三个随机数(pre-master-key)后,通过协商的加密算法计算出本次通信的[会话秘钥]。然后向客户端方最后的信息:
-
加密通信算法改变通知,表示随后的信息都将用[会话秘钥]加密通信。
-
服务器握手阶段结束通知,表示服务器的握手阶段已经结束。同时将之前所有内容发生改变的数据做个摘要,供客户端校验。
至此,整个TLS握手阶段全部结束。接下来客户端与服务端进入加密通信,就完全使用普通的HTTP协议,只不过用[会话秘钥]加密内容。
重点:基于RSA算法的HTTPS存在[前向安全]问题即如果服务器的私钥泄漏,过去被第三方截获的所有TLS通讯秘闻都会被破解。为解决该问题,出现ECDHE密钥协商算法(大多数网站使用的秘钥协商算法)。
5.3.2 客户端校验数字证书的流程?
数字证书签发和验证流程:
数字证书认证机构(CA)签发证书过程,上图左边部分:
-
首先CA会将拥有者的公钥、用途、颁发者、有效时间等信息打成一个包,然后对这些信息进行Hash计算,得到一个Hash值;
-
然后CA使用自己的私钥将Hash值加密,生成Certificate Singnature,即CA对证书签名;
-
最后将Certificate Signature添加在文件证书上,形成数字证书;
客户端校验服务器的数字证书过程,上图右边部分:
-
首先客户端使用同样的Hash算法获取改证书的Hash值H1;
-
通常浏览器和操作系统集成了CA公钥信息,浏览器收到证书后,使用CA的公钥解密Certificate Signature内容,得到一个Hash值H2;
-
最后比较H1和H2的值,相同则为可信赖证书,否则为不可信赖证书。
实际上,证书的验证过程还存在一个证书信任链问题,即我们向CA申请的证书一般不是根证书签发的,而是由中间证书签发的,如百度的证书,证书层次有三级,如图所示:
三级层次关系证书验证过程如下:
-
客户端收到baidu.com证书后,发现这个证书的签发者不是根证书,就无法根据本地已有的根证书中的公钥去验证baid.com证书是否可信。于是客户端根据baidu.com证书中的签发者,找到该证书的颁发机构是“Global Organization Validation CA -SHA256 -G2”,然后向CA请求该中间证书。
-
请求到证书后发现“Global Organization Validation CA -SHA256 -G2”证书是由“GlobalSign Root CA”签发,由于“GlobalSign CA”没有再上级签发机构,说明它是根证书,也就是自签证书。应用软件会检查此证书是否已预载于根证书清单下,如果有则可以利用根证书下的公钥去验证“Global Organization Validation CA -SHA256 -G2”证书,如果通过验证该中检证书是可信的。
-
“Global Organization Validation CA -SHA256 -G2”证书被信任后,可以使用“Global Organization Validation CA -SHA256 -G2”证书汇总的公钥区验证baidu.com证书的可信性,如果验证通过,就可以信任baidu.com证书。
上述三个步骤,最开始客户端只信任根证书Global Root CA证书,然后“Global Root CA“证书信任”Global Organization Validation CA -SHA256 -G2“证书,而”Global Organization Validation CA -SHA256 -G2“证书又信任baidu.com证书,于是客户端信任baidu.com证书
总体来说,他们类似于DNS域名服务器最开始都是从上往下找,一层层往下信任;用户信任 GlobalSign,所以由 GlobalSign 所担保的 baidu.com 可以被信任,另外由于用户信任操作系统或浏览器的软件商,所以由软件商预载了根证书的 GlobalSign 都可被信任。
操作系统一般都会内置一些根证书,这样的一层层验证就构成了一条信任链路,整个证书信任链路验证流程如下图所示:
为什么需要证书链来验证证书,Root CA不直接颁布证书,而是弄那么多中间层级?
为提高根证书的绝对安全性,如果根证书失守,整个信任链都会有问题。
6.HTTP的演变
6.1 HTTP/1.1相比Http/1.0提高了什么性能?
HTTP/1.1相比于HTTP/1.0性能上的改进点:
- 使用长连接改善HTTP/1.0短连接造成的性能开销;
- 支持管道(pipeline)网络传输,第一个请求发出去,不必等其回来,就可以发送第二个请求出去,减少整体响应时间。
HTTP/1.1性能瓶颈:
- 请求/响应头部未经压缩发送,首部信息越多延迟越大,只能压缩Body部分;
- 每次互相发送冗长且相同的首部造成的浪费较多;
- 队头阻塞:服务器按照请求顺序响应,若服务器响应慢,导致客户端一直请求不到数据造成队头阻塞;
- 没有请求优先级控制;
- 请求只能从客户端开始,服务端被动响应
6.2 Http/2做了哪些优化?
HTTP/2.0是基于HTTPS,因此HTTP/2.0是安全的协议
HTTP/2相比HTTP/1.1性能上改进:
- 头部压缩:若发送方同时发送多个相似请求,HTTP/2.0协议会使用HPACK算法在客户端和服务端维护一个头信息表,将所有字段存入该表中,生成索引号。后续信息传输不需要发送同样字段,而是通过发送索引号来传输信息,提高传输效率;
- 二进制格式:HTTP/2.0弃用HTTP/1.1的纯文本格式,全面采用二进制格式。头信息化和数据体都是二进制,并统称为帧(frame):头信息帧和数据帧。该格式对计算机友好,能够增加数据传输效率。
- 并发传输:HTTP/2.0改善HTTP/1.1的请求响应模式,多个Stream复用在一个TCP连接上,Stream中可包含1个或多个Message,一个message对应HTTP/1中的一个请求或响应。一个Message包含一个或多个帧。
- 服务器主动推送资源:
HTTP/2缺陷
HTTP/2通过并发能力解决了HTTP/1对头阻塞问题,但是HTTTP/2还是存在TCP层的队头阻塞问题。HTTP/2是基于TCP协议来传输数据的,TCP是字节流协议,TCP必须保证收到的字节流数据是完整且连续的,这样内核才能将缓冲区里的数据返回给HTTP应用,当[前一个字节数据]没有到达时,后收到的字节数据只能存放到内核缓冲区里,只有当这一个字节数据到达时,HTTP/2应用层才从内核中拿到数据,这就是HTTP/2的TCP队头阻塞。
HTTP/2的TCP队头阻塞流程如下
上图中发送方发送多个package,每个package有自己的TCP序号,其中package3丢失,即使package4-6接收方收到后,由于内核中的TCP数据不是连续的,于是接收方的应用层就无法从内核中读取整个连续数据,只有等到package3重传后,接收方的应用层才能从内核中读取到数据,即HTTP的对头阻塞发生在TCP层。TCP一旦发生丢包现象就会触发TCP重传机制,这样在一个TCP连接中所有的HTTP请求都必须等待这个丢包被重传回来。
6.3 Http/3做了优化?
HTTP/2的队头阻塞是由于TCP协议造成的,因此HTTP/3使用传输层协议是UDP协议,从而解决HTTP/2的TCP层队头阻塞。
UDP发送不管顺序,也不管丢包,因此不会出现HTTP/2队头阻塞问题。UDP是不可靠传输,但基于UDP的QUIC协议可以实现类似TCP的可靠性传输。
QUIC三个特点:
- 无队头阻塞:
- 更快建立连接:
HTTP/3虽然需要QUIC握手,但是此次握手过程只需要一个RTT,握手目的是确认双方的[连接ID]。连接迁移是基于连接ID实现的。但是HTTP/3的QUIC协议并不是TLS分层,而是QUIC内部包含TLS,它在自己的帧会携带TLS里的“记录”,再加上QUIC使用的TLS/1.3,因此仅需1个RTT就可以[同时]完成建立连接与秘钥协商。
- 连接迁移:
7.参考链接
本人博客内容是基于小林coding的计算机网络写的,中间省略了部分内容,大家可以去小林coding博客看更详细的图解网络,链接为:小林coding (xiaolincoding.com)。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY