2 个版本
使用旧的Rust 2015
0.1.1-pre | 2014年12月6日 |
---|---|
0.1.0-pre | 2014年11月21日 |
#331 在 #library
205KB
3.5K SLoC
废弃通知
这个库正在退出。它是一个有用的实验,现在正在Teepee项目的范围内被取代。
有关所有这些发生的更多信息,请参阅 http://chrismorgan.info/blog/introducing-teepee.html.
在Teepee准备使用之前,rust-http将继续维护,以便您可以与Rust master一起使用,但不再对其开展工作。之后,它可能会相当快地减少,并提供迁移指南以帮助您切换到Teepee。只要您没有用它构建大型程序(不推荐!),迁移应该不会太难。
但现在,如果您想在Rust中玩HTTP,这就是您要使用的库。
Rust HTTP库
本项目分为两部分
- HTTP服务器
- HTTP客户端
两者都在进行中;两者都实现了基本、低级的功能。两者都不完整,也还没有任何合规性。
Rust版本
我敦促您跟踪Rust master,就像rust-http一样,但如果您真的想使用Rust 0.9,您可以使用 [rust-0.9-compatible 分支](https://github.com/chris-morgan/rust-http/commits/rust-0.9-compatible)。然而,它没有得到维护;它只是最后一个在Rust 0.9上工作的提交。
目标
本项目当前阶段的目标是,简单地创建一个Rust的通用HTTP服务器和客户端库。
当我提到“通用”时,通用就是我所说的:使用rust-http编写非源服务器(例如代理或网关)是完全可行的;对于源服务器,将仅提供稍微更高层次的抽象可用。
目前这还是一个crate,但它可能被拆分为多个crate(例如,公共HTTP、客户端、服务器);我还不确定这一点。
这个服务器(在正常意义上)没有偏见;它提供工具、处理通信、HTTP/1.1协议和基本头信息,然后将其余部分留给你。像URL路由这样的东西不属于这里;那是框架的领域。
然而,它在一件事情上有强烈的意见:使用类型系统。rust-http强制你编写类型安全的代码。这有利于安全性和正确性,也通常有利于速度。
入门
这是在Ubuntu上开发的,旨在针对Rust的master分支的移动目标。
使用Cargo构建
cargo build
编译示例
cargo test
运行其中一个服务器
target/test/apache_fake
要运行客户端示例,启动其中一个服务器并运行
target/test/client http://127.0.0.1:8001/
目前,所有示例服务器都服务于http://127.0.0.1:8001/。
不要期望一切都能很好地工作。服务器声称支持HTTP/1.1,但尚未在任何方面合规。
SSL支持
rust-http带有SSL支持。
路线图
这里有一些需要完成的事情。它们只是非常模糊地排序,对客户端和服务器相当不区分。
实现HTTP/1.1。
- 处理传输编码,特别是分块(对于支持keep-alive的服务器来说相当基本)。
- 读取请求数据(为了简单起见,首先读取整个请求数据):目前,无法将TcpStream分割成可以同时访问的Reader和Writer;只需认识到这是一个效率和安全的缺陷,稍后将在“增量读取请求数据”中修复)。这是执行像POST这样的操作所必需的。
- 将头信息视为数据,而不是字符串。
- 使处理像cookies、etags和缓存这样的东西变得简单。
测试,很多测试。现在几乎没有。
基准测试,很多基准测试。这将在我的代码层面和运行时层面都有所帮助。
提高HTTP客户端的便利性和正确性。
防止DoS攻击:主要涉及诸如连接超时之类的操作。使用pathod制作测试套件。
效率和防止DoS攻击:增量读取请求数据。
TLS/SSL的实现还很长;在我想将其视为安全的服务器之前,我想要一个独立的审计;现在,通过像Nginx这样的反向代理使用它更安全、更简单,让它负责SSL。
Servo的存在将大大帮助这个项目;在某个阶段,它将需要一个TLS/SSL实现,我们主要可以使用它。
当大多数这些事情完成时,然后我开始开发我的Web框架。它最终会非常快,非常安全,非常方便。但不要计划在2013年使用它。
设计(服务器)
(在本节中,第一人称代词指的是Chris Morgan。)
迄今为止,我主要是一个Python开发者。我开始设计这个项目是通过检查Python的WSGI(PEP 3333),它被认为足够好,以至于Ruby的Rack直接基于它。然而,我很快得出结论,它的设计是为了完全不同的用例;我在Rust中的目标是提供整个服务器,而不是与另一个服务器接口。某些其他设计决策与我的宏伟愿景不相符。以这个例子为例
为什么使用CGI变量而不是传统的HTTP头信息?为什么还要将它们与WSGI定义的变量混合在一起?
许多现有的Web框架都大量基于CGI规范,而现有的Web服务器知道如何生成CGI变量。相比之下,表示传入HTTP信息的替代方式是分散的,并且市场份额有限。因此,使用CGI“标准”似乎是一种利用现有实现的好方法。至于与WSGI变量混合,分离它们只需要传递两个字典参数,而不会提供真正的益处。
在Rust中,没有遵循此类约定的代码库,所以我们不受此要求的束缚。我对这类事情的看法是,对于静态类型世界,有这样的东西并不是有益的。大多数Web系统都会有类似的东西,实际上是与以下类似的Map
response.headers["Date"] = format_http_time(now_utc())
头信息Date是已知的,它是一个日期和时间。为什么不这样呢?
response.headers.date = now_utc()
当然,可能需要未知头信息;即使在那里,也可能不希望有一个String值,而是一个更适合的类型,它实现了将字符串转换为和从字符串转换的特质。
注意,在这些示例中,确切的形式尚未确定。
最终的结果是我决定完全不模拟WSGI。最后,Go的net/http包一直是我的主要灵感来源,但我正在创建一个绝对不同的东西net/http仅作为灵感,然后我做自己的事情。你看,Go缺乏Rust拥有的所有这些美好的事物,比如它的枚举和内置类型之外的迭代。
许可证
此库的发布条款与Rust类似:双许可,MIT许可证和Apache许可证(版本2.0)。
有关详细信息,请参阅LICENSE-APACHE、LICENSE-MIT和COPYRIGHT。
依赖项
~1.6-3.5MB
~68K SLoC