curl的25年之旅(译)

avatar

原文链接:daniel.haxx.se/blog/2023/0…

时光如箭,日月如梭。转眼间curl已经诞生25周年了。

curl项目之初非常低调,最初几年几乎没有人知道这个被重命名的小型URL传输工具。然而它解决了我个人的痛处。

我那时的状态

我发布了第一个版本的curl,并从那时起承担了每个版本的发布。当我发布第一个curl版本的那一天,我27岁,当时在Frontec Tekniksystem担任软件工程师,主要为瑞典大型产品开发公司开展嵌入式系统的合同开发工作。在90年代的几年里,我在电信巨头Ericsson中工作,参与了公司的多个项目。

自从在80年代中期获得第一台计算机以来,我就喜欢编程和开发。在1990年代,我已经建立了一个日常时间表,晚上当我的另一半上床睡觉时,我会熬夜开发,我会在闲暇时间再花上一两个小时进行开发。这基本上是我在前几十年里如何找到时间专注于我的项目的方式,虽然牺牲了一些睡眠和其他事情。

逐渐和持续改进

curl开发的理念一直是不断迭代和改进其所有方面。保留原有行为,但增强代码、添加测试用例、改进文档。年复一年,一次又一次。这个过程从未停止,正如下面的时间线所展示的那样。

类似地,curl并没有突然变得流行起来并迅速拥有大量用户的时刻。相反,用户数量和工具库的受欢迎程度持续地增长。在1998年,用户很少。到了2010年,用户数量已经达到了数亿人。

我们实际上无法准确知道现在有多少用户或libcurl的安装实例。仅仅基于世界上有70亿智能手机和10亿平板电脑这一事实,我们可以估计它至少运行在超过100亿个设备上,而且我们知道其中每个设备至少安装了一个curl,可能还有更多。

在curl之前

我的网络传输之旅始于1996年末,当时我下载了httpget 0.1版本,用于每天自动下载货币汇率,以确保我的IRC机器人可以正确的进行货币兑换转换。httpget存在一些缺陷,所以我发送了修复的补丁回去,但作者Rafael很快决定让我接管这个项目的维护工作。于是我就接手了。

我添加了对GOPHER协议的支持,改变了项目的名称,并在1998年开始添加了FTP上传支持...

1998年

1998年3月20日,发布了curl 4.0版本,它在诞生时已经有2200行代码,因为它是基于之前的httpget和urlget项目构建的。它支持三种协议:HTTP、GOPHER和FTP,并拥有24个常用的命令行选项。

curl的第一个发布并不是特别重要的事件,因为我之前已经发布httpget和urlget的版本一年多了,所以虽然这是一个新的名称,但也只是“又一个发布”,就像我之前做过很多次一样。

我们在第一个curl年度内已经添加了HTTPS和TELNET支持,同时也推出了第一个curl手册。curl最初采用GPL许可证,后来同年切换到了MPL许可证。

第一个SSL支持由SSLeay提供。这个项目在1998年末转变为OpenSSL。

1998年8月,我们在开源目录网站freshmeat.net上添加了curl。

第一个curl网页发布在www.fts.frontec.se/~dast。(顺便提一… machine存档的最早版本是1998年12月的)

1998年11月,我在网站上添加了一个“最新发布的版本已经被下载了300次”的令人震惊的消息,成功和受欢迎程度远非一蹴而就。 1998年11月curl网站截图

在这一年,我们发布了20个curl版本。后来我们再也没有重复过这个壮举。

1999年

我们创建了第一个configure脚本,添加了对cookie的支持,并作为Debian Linux的一个软件包出现。

curl网站迁移到了curl.haxx.nu。

我们这一年添加了对DICT、LDAP和FILE的支持。现在支持8种协议。

在1999年的最后几天,我们将curl代码导入了一个名为Sourceforge的新服务中。从此之后,curl的所有提交计数都从这个导入开始。1999年12月29日。

2000年

我在2000年初换了工作,但白天仍继续进行嵌入式合同开发。

.se域名的规则发生了变化,我们将curl网站迁移到了curl.haxx.se。

我结婚了。

2000年8月,我们发布了curl 7.1版本,事情发生了变化。这个发布引入了我们称之为libcurl的库,因为我们想不出一个更好的名字。此时,项目的代码行数达到了17,200行。

libcurl的API受到了fopen()的启发,它返回一个不透明的句柄,并且可以使用ioctl()来设置选项。

将curl创建为一个库就是我一直以来的想法,因为在那之前我已经意识到一个好的库对应用程序的的重要性。

curl的第一个CVE报告出现了。

用户发现这个库很有用,curl的使用量也增加了。libcurl的最早的使用者之一是PHP语言,他们决定将libcurl作为默认的HTTP/URL传输引擎。

我们创建了第一个测试套件。

2001年

我们更改了许可证,并提供了基于新curl许可证(实际上是MIT许可证)和MPL的curl。稍微修改curl许可证的想法有点疯狂,但原因已经被遗忘。

我们添加了对HTTP/1.1和IPv6的支持。

在六月份,感谢文件中列出了67个贡献者的名字。这是一个团队的努力。我们在三月份超过了1,100个总提交,并且在七月份,curl的代码行数达到了20,000行。

当Mac OS X 10.1中发布curl 7.7.2时,苹果开始与Mac OS X捆绑提供curl。

2002年

测试套件中包含了79个测试用例。

我们放弃了MPL选项。我们再也不会玩许可证变更游戏。

我们添加了对HTTP上的gzip压缩的支持,并学会了如何使用SOCKS代理。

2003年

引入了curl的“自动构建”系统:志愿者在他们的计算机上运行脚本,频繁地下载、构建和运行curl的测试,并将结果通过电子邮件发送回我们的中央服务器进行报告和分析。在现代的CI系统让这些事情变得更加容易之前,我们就已经有了这样的系统。

我们为HTTP添加了Digest、NTLM和Negotiate身份验证的支持。

在八月份,我们提供了40个单独的man页面。

添加了对FTPS的支持,协议号为9。

我的第一个孩子,Agnes,出生了。

我拆分了ares项目,并开始了c-ares项目,为curl和其他项目提供和维护一个用于异步名称解析的库。这个项目从那时起也变得相当受欢迎和广泛使用。

2004年

在2003年初,curl的代码行数为32,700行。

我们使curl支持“大文件”,当时指的是支持大于2和4 GB的文件。

我们实现了对IDN(国际化域名)的支持。

2005年

GnuTLS成为第二个支持的TLS库。用户现在可以选择他们想要使用哪个TLS库进行构建。

感谢瑞典“Internetfonden”的资助,我请了假,可以实现 multi_socket() API 的第一个版本,以允许应用程序更快地进行更多并行传输。

Git诞生了,他们迅速采用了curl进行HTTP(S)传输。

TFTP成为curl支持的第十个协议。

2006年

我们决定放弃对"第三方FTP传输"的支持,这导致了由于修改ABI而提升了SONAME。这是最近一次发生这种情况。它引发了一些争论。我们了解到SONAME的变动对用户来说有多么困难。

wolfSSL的前身cyassl成为curl支持的第三个SSL库。

我们添加了对HTTP/1.1 Pipelining的支持,并在后半年,我接受了Adobe的合同开发工作,并添加了对SCP和SFTP的支持。

作为SCP和SFTP工作的一部分,我迈出了相当大的一步,并且后来成为了libssh2项目的维护者。这个项目也被广泛使用。

我迎来了我的第二个孩子,我的儿子Rex。

2007年

现在,代码行数达到了51,500行,我们添加了对第四个SSL库的支持:NSS。

我们添加了对LDAPS的支持,并合并了首次适用于OS/400的端口。

在curl 7.16.1中,我们添加了对--libcurl的支持。这可能是我最喜欢的curl命令行选项之一。生成使用libcurl的源代码,重复命令行传输。

四月份,curl有348个测试用例。

2008年

此时,命令行工具的功能已经增长到拥有126个命令行选项。在curl的前十年中,增长了5倍。

三月份,我们超过了10,000次提交。

我加入了httpbis工作组的邮件列表,并开始积极参与IETF和HTTP协议的工作。

Solaris发布了curl和libcurl。Linux上的Adobe Flash播放器使用libcurl。

九月份,curl贡献者的总数达到了654人。

2009年

在FLOSS Weekly 51上,我第一次在播客中谈到了curl。

我们引入了使用cmake构建curl的支持。这个决定仍然在讨论中,并且有人质疑它是否真的有帮助。为了使循环完整,cmake本身使用libcurl。

七月份,IETF 75会议在我家乡斯德哥尔摩举行,这是我第一次有机会亲自见到几位我个人认为的协议英雄,他们创建并继续致力于HTTP协议:Mark、Roy、Larry、Julian等等。

八月份,我辞去工作,开始为我自己的公司Haxx工作,但仍继续进行合同开发。当时主要从事嵌入式Linux开发。

由于另一份合同的支持,我为curl引入了对IMAP(S)、SMTP(S)和POP3(S)的支持,将支持的协议数量提升到19个。

我荣获了2009年度北欧自由软件奖,表彰我在curl、c-ares和libssh2上的工作。

2010年

我们添加了对RTSP和RTMP(S)的支持。

PolarSSL成为第六个受支持的SSL库。

我们从CVS切换到了Git版本管理系统,并同时将托管平台从Sourceforge切换到GitHub。从这一点开始,我们正确且适当地跟踪提交的作者,这在CVS中更加困难。

添加了对AxTLS库的支持,成为第七个受支持的库。

2011年

代码行数超过了80,000行。

发布了cookie RFC 6265。我参与其中,并做出了一些小的贡献。

我们引入了checksrc脚本,用于验证源代码是否符合curl的代码风格。一开始很简单,随着时间的推移,不断进行改进并变得更加严格。

我收到了一些来自谷歌员工的感谢,最终获得了一些谷歌的纪念品。

我们超过了100名个人贡献者。

2012年

拥有149个命令行选项。

添加了对Schannel和Secure Transport的支持,用于TLS。

当我尝试估算curl用户数量时,我估计有5.5亿用户。这是我早期意识到curl无处不在的重要发现之一!

整个2012年,共有67位提交作者。

2013年

添加了对GSKit的支持,这是一个在OS/400上广泛使用的TLS库,成为第十个受支持的TLS库。

四月份,贡献者数量超过了1,000人,并且我们的测试用例超过了800个。

我们重构了内部结构,确保所有操作都是非阻塞的,并使用“内部使用多连接”(use multi internally)的方式,使得易用的接口只是对多连接传输的一个封装。

最初的HTTP/2支持尝试被合并(使用了出色的nghttp2库),以及使用Happy Eyeballs方法进行连接的支持。

我们创建了我们的第一个两个CI作业。

2014年

我开始在Mozilla的Firefox网络团队工作,在瑞典的家中远程工作。这是我职业生涯中第一次真正主要从事网络和HTTP等工作,与curl的重叠部分很大。直到这个时候,我生活的两个方面一直奇怪地分开。Mozilla允许我在工作时间中花一些时间来开发curl。

拥有161个命令行选项和20个已报告的CVE漏洞。

在7月份,59个man页面变成了270个man页面,每个libcurl选项都有自己单独的页面。

我们添加了对libressl OpenSSL分支的支持,并移除了对QsoSSL的支持。仍然支持10个TLS库。

到了9月份,代码行数达到了105,000行。

添加了对SMB(S)的支持,总共支持24个协议。

2015年

添加了对BoringSSL和mbedTLS的支持。

我们引入了对使用HTTP/2进行正确复用传输的支持。这是架构上的一次相当重大的范式变化,当多个传输共享一个连接。为此我们进行了许多重构工作,直到HTTP/2支持稳定下来,这需要一段时间。

随后我们首次支持了HTTP/2服务器推送。

我们完全转向了GitHub的工作模式,使用其问题跟踪器并进行拉取请求。

HTTP/2的第一个RFC于5月份发布。我想自己对其背后的工作组努力做出了一点贡献。

今年,我的HTTP/2工作部分由Netflix赞助,同时我仍然受雇于Mozilla并为其工作,这需要我对我的工作作出一些调整。

达到了20,000个提交。

我开始写《everything curl》。

我们还添加了对libpsl的支持,使用公共后缀列表(Public Suffix List)来改进cookie处理。

2016年

curl默认使用HTTP/2进行HTTPS传输。

在5月份,curl拥有185个命令行选项。

我们有了一个新的logo,现在的logo由Soft Dreams的Adrian Burcea设计。

添加了对HTTPS代理和TLS 1.3的支持。

curl接受了Cure 53的审计。

因为我对curl的贡献,一家名为Sweclockers的瑞典技术网站将我评为瑞典第二优秀的开发者。

年底时,代码行数达到了115,500行。

2017年

curl开始支持使用多个TLS库进行构建和使用,并在启动时进行选择。

Fastly慷慨地提供了curl网站以及我的个人网站的托管。这帮助解决了之前当博客文章过于受欢迎而导致网站无法正常运行的问题,并使全球范围内更多人可以更快地访问curl网站。他们一直是该项目的忠实赞助商。

在2017年春天,我们举办了有史以来的第一次实体开发者大会,名为curl up。作为20多名curl的粉丝和开发者,我们前往了德国纽伦堡, 在那里我们整个周末都在进行与curl相关的活动。

在6月份,我被拒绝前往美国旅行。这之后我为了获得美国签证,进行了很长时间的努力。

首次引入了SSLKEYLOGFILE支持,我们还推出了新的MIME API和对brotli压缩的支持。

curl项目被纳入OSS-Fuzz项目,该项目指出了我们代码中的错误。从那时起,他们一直持续对curl进行黑盒测试。

在10月份,我获得了Polhem奖。这是瑞典最古老、最具声望的工程奖项。该奖项自1876年设立以来一直颁发。一枚真正的金质奖章,由瑞典国王亲自颁给我。奖章上刻有我的名字。

2018年

添加了对DNS over HTTPS的支持,并引入了新的URL API,允许应用程序以与curl完全相同的方式解析URL。

我参加了Changelog播客,谈到了curl成立20年的情况。

微软开始在Windows中绑定curl。但curl的别名仍然存在。

我们引入了对第二个SSH库的支持,因此现在SCP和SFTP可以使用libssh和之前支持的libssh2库来进行操作。

我们添加了对MesaLink的支持,但停止支持AxTLS。支持12个TLS库。

代码行数达到了129,000行。在GitHub上获得了10,000个星标。

为了接受捐赠,我们被要求在Open Collective上创建一个账户,于是我们这样做了。这对于项目接收捐款和赞助来说是一个良好的渠道。

2018年11月,决定HTTP-over-QUIC协议正式成为HTTP/3。

年底时,拥有27个CI作业,运行了1200多个测试用例。

2019年

我开始全职从事curl工作,加入了wolfSSL。花了21年的时间,终于让curl成为了我的工作。

我们添加了对Alt-Svc的支持,并移除了一直存在问题的HTTP/1.1 Pipelining支持。

我们推出了第一个curl漏洞赏金计划,并且自那以后一直有一个漏洞赏金计划在运行。与hackerone合作。我们支付了近5万美元的奖励金用于奖励45个漏洞(截至2023年2月)。

添加了对AmiSSL和BearSSL的支持,使得支持的TLS库达到了14个。

我们合并了对HTTP/3的初始支持,使用了quiche库,之后还引入了第二个库:ngtcp2。那么为什么不使用多个后端呢?

我们开始提供一个“官方”的docker镜像中的curl。

2020年

curl工具获得了并行传输功能,在-w选项中支持以JSON格式输出数据,并且重新整理并更好地分为子类别的--help输出变得更加清晰。

在2020年3月,针对curl 7.69.0版本,我开始做发布视频演示,并且进行了直播。

curl网站迁移到了curl.se,而everything curl则迁移到了curl.dev域名下。

MQTT成为第25个支持的协议。

首次添加了对HSTS的支持,以及对zstd压缩的支持。

wolfSSH成为第三个支持的SSH库。

我们停止支持PolarSSL。

初始支持将hyper作为HTTP/1和HTTP/2的替代后端。

在11月,在新冠疫情肆虐期间,我终于获得了美国签证。

在年底之前,创建了第90个CI作业。

2021年

停止支持MesaLink,但添加了对rustls的支持,使得支持的TLS库达到了13个。

Ingenuity成功降落在火星上,curl对此提供了一些帮助。

我收到了一封非常不愉快的死亡威胁邮件,发件人深陷困惑之中,责怪我造成了他遭遇的各种不幸。

在GitHub上获得了2万个星标。

支持GOPHERS协议,共支持26个协议。

在这一年中,共有187位个人撰写的提交被合并。

2022年

合并了对WebSocket(WS://和WSS://URL)的初始支持,并引入了一个新的处理WebSocket的API。共支持28个协议。

我们添加了--json命令行选项,并且libcurl获得了一个新的头部API,这也使得命令行工具增加了对-w选项的“选择头部”功能。我们还添加了--rate和--url-query选项。

HTTP/3的RFC于6月发布。

msh3成为第三个支持的HTTP/3库。

Trail of Bits进行了一次由OpenSSF赞助的curl安全审计。

12月进行了第212个curl发布。在GitHub上创建了第10,000个问题。

2023年

年初情况:代码有155,100行、486个手册页、1560个测试用例、2,771位贡献者、1,105位提交作者、132个CVE、122个CI作业、29,733次提交、以48,580美元的奖励金奖励了漏洞赏金计划、249个命令行选项、28个协议、13个TLS库、3个SSH库、3个HTTP/3库。

引入对HTTP/3的支持,并回退到旧版本,使其使用更加可靠。

在3月13日,我们的提交次数超过了30,000次。

在3月20日,我们发布了curl 8.0.0版本。正好是自第一个curl发布以来的25年。

保持相关性

在过去的25年里,我们停止使用并遗忘了许多软件、工具和服务。事物来了又走。每个事物都有它的时代,许多项目在某个时刻无法跟上时代的脚步并被其他东西取代。

我希望curl一直是一个非常重要的软件项目,拥有众多用户和用例。我认为这部分是因为我们积极地维护它,用心和热爱地对待它。我们让它做用户想让它做的事情。跟上时代,保持最新版本,支持最新的安全措施,成为你想使用和参与的项目。以身作则。

我的生活永远都离不开curl

能够将curl发展到这一步并全职从事我的爱好项目,是我一直所追求的事情。curl已经成为我生活中的重要一部分。

在2019年葡萄牙度假时的我

然而,curl是一个团队的努力,如果没有我们所有伟大的贡献者,它就不可能诞生并且如此受欢迎。有些人会称我为“curl之父”,或说这是“我的”项目,但所有了解这个项目的人都知道,团队中的成员远不止我一个。

25年

那天,当我开始编写httpget时,我26岁。我在27岁时发布了curl。去年11月,我过了52岁生日。

我在curl上工作的时间比在任何一家公司工作的时间都要长。我的孩子们都没有这么大。25年前,我还没有住在现在的房子里。25年前,Google和Firefox都不存在。

许多现在使用curl的用户在我开始工作时甚至还未出生。

二十五年之后

我觉得有必要加上这一部分,因为人们会问。

我不知道未来会带来什么。我从来不擅长预测未来,坦率地说,我总是尽量避免预测。我希望能继续参与这个项目,继续为客户端的互联网传输工作,只要它对人们有帮助,人们愿意使用我的工作成果。

我会在另外25年内继续参与这个项目吗?curl在那时是否还会保持相关性?我不知道。让我们拭目以待!