Delphi HTTP/2 客户端与服务器——多路复用、流式传输、推送

RFC 9113 HTTP/2 的原生 Pascal 实现——流多路复用、HPACK 标头压缩、流量控制、服务器推送以及 WebSocket-over-HTTP/2 扩展 (RFC 8441)。客户端或服务器使用同一组件,从 Delphi 7 到 Delphi 13。

纯 Pascal HTTP/2 栈

不是 WinHTTP 或 libcurl 的薄包装——而是从零开始的实现,让您拥有帧级控制。

Delphi HTTP/2 客户端不再可选:HTTP/2 是整个现代 Web 使用的线格式。Apple Push Notifications 要求 HTTP/2。Google API 协商 HTTP/2。AWS、Azure 和 CloudFront 默认使用 HTTP/2。收益是实实在在的:单个 TCP/TLS 连接复用数十个进行中的请求,标头集使用 HPACK 压缩,服务器可以推送客户端尚未请求的资源。sgcWebSockets 提供 TsgcHTTP2Client(客户端)以及在 TsgcWebSocketHTTPServer 内的 HTTP/2 支持(服务器)——两者都是纯 Pascal,都在 Delphi 编译器面向的每个平台上运行。

同一库中的 Delphi HTTP/2 服务器可以托管 REST API、向长期客户端推送事件,以及在 HTTP/2 上接受 WebSocket 升级 (RFC 8441)——这是现代基础设施在 HTTP/2 / HTTP/3 之上分层 WebSocket 的标准方式。

客户端

TsgcHTTP2Client

服务器

启用 HTTP/2 的 TsgcWebSocketHTTPServer

标准

RFC 9113 (HTTP/2)、RFC 7541 (HPACK)、RFC 8441 (WS-over-H2)

TLS

OpenSSL、SChannel、HTTP.sys——经 ALPN 协商

为什么 HTTP/2 很重要

相比 HTTP/1.1 的四个大胜利——以及让它们发挥作用的运营细节。

流多路复用

在单个 TCP+TLS 连接上最多 SETTINGS_MAX_CONCURRENT_STREAMS 个进行中的请求——没有队头阻塞,无需调优连接池。

HPACK 压缩

每连接的静态 + 动态标头表消除了膨胀 HTTP/1.1 流量的重复标头(cookies、user-agent、accept)的千字节开销。

服务器推送

服务器可以在客户端请求之前主动发送客户端将需要的资源(CSS、JS、JSON 子资源)——节省一次请求往返。

流优先级

每流权重和依赖树让您可以告诉服务器在 analytics blob 之前发送索引文档。

流量控制

每流和每连接的 WINDOW_UPDATE 防止慢速消费者淹没发送者——背压内置于线格式。

ALPN 协商

TLS 层 ALPN 自动协商 h2——客户端和服务器在第一个请求之前就 HTTP/2 达成一致,如果对等方不支持,则回退到 HTTP/1.1。

WebSocket-over-HTTP/2

RFC 8441:在一个 HTTP/2 流内隧道传输 WebSocket 会话——通过每个 HTTP/2 感知的负载均衡器(Envoy、nginx、ALB、GCLB)运行。

Trailers 和 gRPC 友好

HTTP trailers(按 RFC 7230)是一等公民——这是 gRPC 状态/消息元数据的基础。

多路复用 GET 请求

在单个连接上触发 10 个并发 GET——HPACK 和多路复用让这变得寻常。

uses
  sgcHTTP2_Client, sgcHTTP_Classes;

var
  HTTP2: TsgcHTTP2Client;
  i: Integer;
begin
  HTTP2 := TsgcHTTP2Client.Create(nil);
  HTTP2.Host := 'api.example.com';
  HTTP2.Port := 443;
  HTTP2.TLS  := True;
  HTTP2.TLSOptions.ALPNProtocols.Add('h2');
  HTTP2.OnResponse := DoResponse;

  HTTP2.Connect;

  // 10 concurrent GETs on ONE connection, ONE TLS handshake
  for i := 1 to 10 do
    HTTP2.Get(Format('/items/%d', [i]));
end;

procedure TForm1.DoResponse(Sender: TObject;
  const aStreamId: Cardinal;
  aHeaders: TsgcHTTP2Headers;
  aData: TBytes);
begin
  Memo1.Lines.Add(Format('stream %d  status %s  bytes %d',
    [aStreamId, aHeaders.Status, Length(aData)]));
end;

在客户端请求之前推送子资源

在 OnCommandGet 处理程序内,调用 PushPromise 与 /index.html 一起主动发送 /style.css

uses
  sgcWebSocket, sgcHTTP_Classes;

procedure TForm1.WSServerCommandGet(Sender: TObject;
  aContext: TsgcWSConnection;
  ARequestInfo: TsgcWSRequestInfo;
  AResponseInfo: TsgcWSResponseInfo);
begin
  if ARequestInfo.URI = '/index.html' then
  begin
    // Push the CSS so the browser doesn’t round-trip for it
    AResponseInfo.PushPromise('/style.css');
    AResponseInfo.PushPromise('/app.js');

    AResponseInfo.ContentType := 'text/html; charset=utf-8';
    AResponseInfo.ContentText :=
      '<!doctype html><link rel="stylesheet" href="/style.css">' +
      '<script src="/app.js" defer></script>' +
      '<h1>HTTP/2 from Delphi</h1>';
  end;
end;

HTTP/2 是必需而非可选的场景

Apple Push Notifications

APNs 只接受 HTTP/2——一个持久连接,每秒数千个流,基于 JWT 或证书的身份验证。请参阅 Apple Push 页面。

Google FCM v1

HTTP v1 FCM API 运行在 HTTP/2 上。请参阅 Google FCM 页面。

gRPC 服务

gRPC 是带 protobuf 和 trailers 的 HTTP/2。此处的 HTTP/2 栈是 Pascal gRPC 客户端构建的基础。

WebSocket-over-HTTP/2

通过偏好 HTTP/2 上游的现代负载均衡器和 CDN 部署 WebSocket 最干净的方式。

高吞吐量 REST 客户端

一个连接,数百个进行中的请求——非常适合爬虫、市场数据采集器和扇出工作者。

长轮询替代

在单个 HTTP/2 流上流式传输 JSON-lines 或 SSE 风格的响应——背压包含在内。

深入探讨

HTTP/2 参考

HTTP/2 客户端和服务器的完整组件参考。

HTTP/2 客户端

专门的客户端组件页面。

HTTP/2 服务器

专门的服务器组件页面。

WebSocket 组件

基于 HTTP/2 (RFC 8441) 和基于 HTTP/1.1 (RFC 6455) 的 WebSocket。

博客:HTTP/2 初始服务器支持

原始公告和设计说明。

博客:HTTP/2 vs HTTP/1 性能

多路复用和 HPACK 增益的基准数字。

博客:HTTP/2 一致性测试

针对服务器运行 h2spec 套件。

博客:HTTP/2 上的 APNs

实用的 HTTP/2 示例:APNs 通知。

今天就多路复用您的请求

下载试用版——HTTP/2 客户端和服务器演示开箱即用编译。