<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Документация on poseidon-http-client</title><link>https://lodgvideon.github.io/poseidon-http-client/ru/docs/</link><description>Recent content in Документация on poseidon-http-client</description><generator>Hugo</generator><language>ru</language><atom:link href="https://lodgvideon.github.io/poseidon-http-client/ru/docs/index.xml" rel="self" type="application/rss+xml"/><item><title>Начало работы</title><link>https://lodgvideon.github.io/poseidon-http-client/ru/docs/getting-started/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lodgvideon.github.io/poseidon-http-client/ru/docs/getting-started/</guid><description>&lt;h1 id="начало-работы"&gt;Начало работы&lt;a class="anchor" href="#%d0%bd%d0%b0%d1%87%d0%b0%d0%bb%d0%be-%d1%80%d0%b0%d0%b1%d0%be%d1%82%d1%8b"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;poseidon-http-client — низкоуровневый HTTP-клиент для Go. Он реализует HTTP/1.1, HTTP/2 и HTTP/3 с нуля — собственный фрейминг, HPACK, QPACK и QUIC-стек — без &lt;code&gt;net/http&lt;/code&gt; и без сторонних протокольных библиотек. Клиент рассчитан на генераторы нагрузки и инструменты, которым нужен прямой контроль над соединениями, стримами и flow control.&lt;/p&gt;
&lt;h2 id="установка"&gt;Установка&lt;a class="anchor" href="#%d1%83%d1%81%d1%82%d0%b0%d0%bd%d0%be%d0%b2%d0%ba%d0%b0"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Требуется Go 1.25 или новее.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;go get github.com/lodgvideon/poseidon-http-client&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="модель-запроса"&gt;Модель запроса&lt;a class="anchor" href="#%d0%bc%d0%be%d0%b4%d0%b5%d0%bb%d1%8c-%d0%b7%d0%b0%d0%bf%d1%80%d0%be%d1%81%d0%b0"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Все три версии протокола используют один и тот же API. Клиент создаётся конструктором, затем вызывается &lt;code&gt;Do&lt;/code&gt; с контекстом, запросом и принадлежащим вызывающему коду &lt;code&gt;*client.Response&lt;/code&gt;:&lt;/p&gt;</description></item><item><title>HTTP/1.1</title><link>https://lodgvideon.github.io/poseidon-http-client/ru/docs/http1/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lodgvideon.github.io/poseidon-http-client/ru/docs/http1/</guid><description>&lt;h1 id="http11"&gt;HTTP/1.1&lt;a class="anchor" href="#http11"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Используйте HTTP/1.1, когда целевой сервер не поддерживает HTTP/2, или
когда нужно проверить именно его HTTP/1.1-путь и не дать ALPN-переговорам
поднять соединение до h2.&lt;/p&gt;
&lt;p&gt;У HTTP/1.1 тот же набор конструкторов, что у HTTP/2 и HTTP/3:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Конструктор&lt;/th&gt;
					&lt;th&gt;Транспорт&lt;/th&gt;
					&lt;th&gt;Схема&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;NewH1Client(addr, dialer, opts...)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;TransportH1SingleConn&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Одно соединение, автоматическое переподключение. Запросы выполняются последовательно.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;NewH1PoolClient(addr, dialer, pool, opts...)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;TransportH1Pool&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;До &lt;code&gt;MaxConnsPerHost&lt;/code&gt; соединений. Это число и есть конкурентность запросов.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;NewManagedH1Client(resolver, dialer, opts...)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;TransportH1Managed&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Service discovery через Resolver + Selector; на каждый адрес — свой HTTP/1.1-подпул.&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="принудительный-http11"&gt;Принудительный HTTP/1.1&lt;a class="anchor" href="#%d0%bf%d1%80%d0%b8%d0%bd%d1%83%d0%b4%d0%b8%d1%82%d0%b5%d0%bb%d1%8c%d0%bd%d1%8b%d0%b9-http11"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Протокол фиксируют две вещи:&lt;/p&gt;</description></item><item><title>HTTP/2</title><link>https://lodgvideon.github.io/poseidon-http-client/ru/docs/http2/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lodgvideon.github.io/poseidon-http-client/ru/docs/http2/</guid><description>&lt;h1 id="http2"&gt;HTTP/2&lt;a class="anchor" href="#http2"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;HTTP/2-клиент реализует RFC 7540 и HPACK (RFC 7541) с нуля — без &lt;code&gt;net/http&lt;/code&gt; и без &lt;code&gt;golang.org/x/net/http2&lt;/code&gt;. Три конструктора покрывают типовые топологии: одно соединение, пул на хост или набор бэкендов, управляемый резолвером. Все три возвращают &lt;code&gt;*client.Client&lt;/code&gt; с одним и тем же API &lt;code&gt;Do&lt;/code&gt; / &lt;code&gt;DoStream&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="одно-соединение"&gt;Одно соединение&lt;a class="anchor" href="#%d0%be%d0%b4%d0%bd%d0%be-%d1%81%d0%be%d0%b5%d0%b4%d0%b8%d0%bd%d0%b5%d0%bd%d0%b8%d0%b5"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;client.NewSingleConnClient&lt;/code&gt; держит одно соединение и автоматически переподключается при обрыве. Это &lt;code&gt;examples/http2/main.go&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Command http2-example issues a single HTTP/2 GET with the poseidon client.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// TransportSingleConn (the default) negotiates h2 over TLS and reuses one&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// connection with automatic redial.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//	go run ./examples/http2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;context&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;crypto/tls&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/lodgvideon/poseidon-http-client/client&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/lodgvideon/poseidon-http-client/conn&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewSingleConnClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;www.cloudflare.com:443&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TLSDialer&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;tls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;			&lt;/span&gt;&lt;span class="nx"&gt;ServerName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;www.cloudflare.com&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;			&lt;/span&gt;&lt;span class="nx"&gt;NextProtos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;h2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;build client: %v&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;cancel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="c1"&gt;// Response is caller-owned and reusable; Reset() clears it between requests.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Do&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;/&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;		&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;GET /: %v&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;	&lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;HTTP/2 %d — %d bytes\n&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Response&lt;/code&gt; принадлежит вызывающему коду: выделите его один раз и вызывайте &lt;code&gt;resp.Reset()&lt;/code&gt; между запросами. &lt;code&gt;client.GET(path)&lt;/code&gt; — сокращённая форма; для полного контроля соберите &lt;code&gt;client.Request{Method, Scheme, Authority, Path, BodyMode}&lt;/code&gt; вручную.&lt;/p&gt;</description></item><item><title>HTTP/3</title><link>https://lodgvideon.github.io/poseidon-http-client/ru/docs/http3/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lodgvideon.github.io/poseidon-http-client/ru/docs/http3/</guid><description>&lt;h1 id="http3"&gt;HTTP/3&lt;a class="anchor" href="#http3"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Клиент HTTP/3 (RFC 9114) работает поверх стека QUIC (RFC 9000/9001/9002) и кодека QPACK (RFC 9204), реализованных в этом репозитории — без &lt;code&gt;quic-go&lt;/code&gt;, без cgo. Из стандартной библиотеки берётся только сам хендшейк TLS 1.3 (&lt;code&gt;crypto/tls&lt;/code&gt;); защита пакетов, восстановление после потерь, управление перегрузкой и flow control — код poseidon.&lt;/p&gt;
&lt;p&gt;API запросов — те же &lt;code&gt;Do&lt;/code&gt; / &lt;code&gt;DoStream&lt;/code&gt;, что и в HTTP/2. &lt;code&gt;client.Request&lt;/code&gt; и &lt;code&gt;client.Response&lt;/code&gt; не меняются при смене транспорта; перевод нагрузочного теста с H2 на H3 — это замена конструктора.&lt;/p&gt;</description></item><item><title>Возможности и преимущества</title><link>https://lodgvideon.github.io/poseidon-http-client/ru/docs/features/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lodgvideon.github.io/poseidon-http-client/ru/docs/features/</guid><description>&lt;h1 id="возможности-и-преимущества"&gt;Возможности и преимущества&lt;a class="anchor" href="#%d0%b2%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b8-%d0%bf%d1%80%d0%b5%d0%b8%d0%bc%d1%83%d1%89%d0%b5%d1%81%d1%82%d0%b2%d0%b0"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id="матрица-поддержки"&gt;Матрица поддержки&lt;a class="anchor" href="#%d0%bc%d0%b0%d1%82%d1%80%d0%b8%d1%86%d0%b0-%d0%bf%d0%be%d0%b4%d0%b4%d0%b5%d1%80%d0%b6%d0%ba%d0%b8"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Все три версии протокола используют один и тот же API запросов: &lt;code&gt;client.Do&lt;/code&gt; / &lt;code&gt;client.DoStream&lt;/code&gt; с переиспользуемым &lt;code&gt;client.Response&lt;/code&gt;, которым владеет вызывающий код. Сжатие тоже общее: ответы декодируются во всех четырёх кодировках — gzip, deflate, br и zstd (клиент отправляет &lt;code&gt;accept-encoding: gzip, deflate, br, zstd&lt;/code&gt;), а &lt;code&gt;Request.CompressBody&lt;/code&gt; сжимает тела запросов — см. &lt;a href="#%d1%81%d0%b6%d0%b0%d1%82%d0%b8%d0%b5"&gt;Сжатие&lt;/a&gt; ниже. Различается лишь то, какую часть протокола открывает каждый транспорт.&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Протокол&lt;/th&gt;
					&lt;th&gt;Реализация&lt;/th&gt;
					&lt;th&gt;Конструкторы&lt;/th&gt;
					&lt;th&gt;Параллельные запросы в одном соединении&lt;/th&gt;
					&lt;th&gt;Пул соединений&lt;/th&gt;
					&lt;th&gt;Service discovery&lt;/th&gt;
					&lt;th&gt;Ключевые возможности&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;HTTP/1.1&lt;/td&gt;
					&lt;td&gt;С нуля&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;NewH1Client&lt;/code&gt;, &lt;code&gt;NewH1PoolClient&lt;/code&gt;, &lt;code&gt;NewManagedH1Client&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Нет — один обмен на соединение в каждый момент (без pipelining)&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;NewH1PoolClient&lt;/code&gt; (пул с эксклюзивной выдачей: &lt;code&gt;MaxConnsPerHost&lt;/code&gt; и есть параллелизм запросов)&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;NewManagedH1Client&lt;/code&gt; (Resolver + Selector)&lt;/td&gt;
					&lt;td&gt;Keep-alive и переиспользование соединений; тела запросов передаются потоком (&lt;code&gt;Request.BodyReader&lt;/code&gt;, chunked, если длина заранее неизвестна), но ответы всегда буферизуются в &lt;code&gt;Response.Body&lt;/code&gt; — &lt;code&gt;DoStream&lt;/code&gt; и &lt;code&gt;BodyStream&lt;/code&gt; возвращают ошибку; цель ALPN-фолбэка: &lt;code&gt;TransportALPN&lt;/code&gt; автоматически выбирает HTTP/1.1, если сервер не предлагает h2&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;HTTP/2&lt;/td&gt;
					&lt;td&gt;RFC 7540 + HPACK (RFC 7541), с нуля&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;NewSingleConnClient&lt;/code&gt;, &lt;code&gt;NewPoolClient&lt;/code&gt;, &lt;code&gt;NewManagedClient&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Да — мультиплексирование потоков, ограниченное &lt;code&gt;MAX_CONCURRENT_STREAMS&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;NewPoolClient&lt;/code&gt; (пул на хост, выбор наименее загруженного соединения, вытеснение простаивающих)&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;NewManagedClient&lt;/code&gt; (Resolver + Selector)&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;DoStream&lt;/code&gt; и трейлеры запроса; управление потоком (flow control); динамические SETTINGS; корректное завершение по GOAWAY; PING keepalive; server push (PUSH_PROMISE); приоритеты запросов; extended CONNECT (RFC 8441, WebSockets поверх H2); CONTINUATION; прокси-диалеры HTTP CONNECT; h2c prior knowledge&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;HTTP/3&lt;/td&gt;
					&lt;td&gt;RFC 9114 + QUIC (RFC 9000/9001/9002) + QPACK (RFC 9204), с нуля&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;NewH3Client&lt;/code&gt;, &lt;code&gt;NewH3PoolClient&lt;/code&gt;, &lt;code&gt;NewManagedH3Client&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Да — параллельные запросы в рамках одного QUIC-соединения&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;NewH3PoolClient&lt;/code&gt; (пул из нескольких соединений)&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;NewManagedH3Client&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;DoStream&lt;/code&gt;; динамический QPACK в обоих направлениях (кодирование и декодирование); все AEAD-шифры TLS 1.3 (AES-128-GCM, AES-256-GCM, ChaCha20-Poly1305); контроль перегрузки — NewReno по умолчанию, BBR по выбору; на Linux: пакетная отправка через GSO, пакетный приём через GRO, ограниченная коалесценция ACK&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;У HTTP/1.1 тот же набор конструкторов, что и у двух других версий, но его пул устроен иначе. В HTTP/1.1 нет мультиплексирования: одно соединение — это строго последовательные запросы, поэтому без пула клиент вообще не может генерировать нагрузку по HTTP/1.1. Пул выдаёт соединения в эксклюзивное пользование — один обмен на соединение в каждый момент, — так что &lt;code&gt;MaxConnsPerHost&lt;/code&gt; и есть параллелизм запросов; &lt;code&gt;MaxStreamsPerConn&lt;/code&gt; не применяется. Запрос, заставший все соединения занятыми, ждёт освобождения одного из них — ожидание ограничено контекстом запроса. Соединения поддерживаются живыми и переиспользуются; &lt;code&gt;Connection: close&lt;/code&gt;, мёртвое соединение или ошибка обмена приводят к сбросу соединения и повторному подключению. Pipelining сознательно не реализован. Диалер не должен предлагать ALPN-токен &lt;code&gt;h2&lt;/code&gt; — используйте обычный TCP-диалер или TLS-диалер, у которого в &lt;code&gt;NextProtos&lt;/code&gt; только &lt;code&gt;&amp;quot;http/1.1&amp;quot;&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Отказ от ответственности</title><link>https://lodgvideon.github.io/poseidon-http-client/ru/docs/disclaimer/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lodgvideon.github.io/poseidon-http-client/ru/docs/disclaimer/</guid><description>&lt;h1 id="отказ-от-ответственности"&gt;Отказ от ответственности&lt;a class="anchor" href="#%d0%be%d1%82%d0%ba%d0%b0%d0%b7-%d0%be%d1%82-%d0%be%d1%82%d0%b2%d0%b5%d1%82%d1%81%d1%82%d0%b2%d0%b5%d0%bd%d0%bd%d0%be%d1%81%d1%82%d0%b8"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;poseidon-http-client — молодая библиотека. Это её первый релиз. Прочитайте эту страницу, прежде чем на неё полагаться.&lt;/p&gt;
&lt;h2 id="без-гарантий"&gt;Без гарантий&lt;a class="anchor" href="#%d0%b1%d0%b5%d0%b7-%d0%b3%d0%b0%d1%80%d0%b0%d0%bd%d1%82%d0%b8%d0%b9"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Библиотека распространяется под лицензией MIT и предоставляется &lt;strong&gt;как есть&lt;/strong&gt;, без каких-либо гарантий. Вы используете её на свой страх и риск. Точные условия — в файле &lt;a href="https://github.com/lodgvideon/poseidon-http-client/blob/main/LICENSE"&gt;LICENSE&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="критичный-для-безопасности-код-без-стороннего-аудита"&gt;Критичный для безопасности код без стороннего аудита&lt;a class="anchor" href="#%d0%ba%d1%80%d0%b8%d1%82%d0%b8%d1%87%d0%bd%d1%8b%d0%b9-%d0%b4%d0%bb%d1%8f-%d0%b1%d0%b5%d0%b7%d0%be%d0%bf%d0%b0%d1%81%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%ba%d0%be%d0%b4-%d0%b1%d0%b5%d0%b7-%d1%81%d1%82%d0%be%d1%80%d0%be%d0%bd%d0%bd%d0%b5%d0%b3%d0%be-%d0%b0%d1%83%d0%b4%d0%b8%d1%82%d0%b0"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Библиотека реализует с нуля протоколы, критичные для безопасности: транспорт QUIC (RFC 9000/9001/9002), защиту записей TLS 1.3 для QUIC, HPACK (RFC 7541) и QPACK (RFC 9204). На этих путях она не использует &lt;code&gt;net/http&lt;/code&gt;, &lt;code&gt;quic-go&lt;/code&gt; или какую-либо другую устоявшуюся реализацию протоколов.&lt;/p&gt;</description></item></channel></rss>