summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2023-01-24 10:03:59 +0100
committerLoïc Hoguin <[email protected]>2023-01-24 10:03:59 +0100
commitc150ffb220c15f10076b86fb2776a782a4d098ae (patch)
tree22b7650b798bdcaad4c0cd59b0c2f4b231717931
parentd73aae065ac85cd7de71b815c1c8f28df6391828 (diff)
downloadninenines.eu-c150ffb220c15f10076b86fb2776a782a4d098ae.tar.gz
ninenines.eu-c150ffb220c15f10076b86fb2776a782a4d098ae.tar.bz2
ninenines.eu-c150ffb220c15f10076b86fb2776a782a4d098ae.zip
Gun 2.0
-rw-r--r--_build/content/articles/gun-2.0.0.asciidoc80
-rw-r--r--_build/data/projects/gun.toml4
-rw-r--r--articles/asciideck/index.html4
-rw-r--r--articles/cowboy-2.0.0-pre.4/index.html4
-rw-r--r--articles/cowboy-2.0.0-rc.1/index.html4
-rw-r--r--articles/cowboy-2.0.0-rc.2/index.html4
-rw-r--r--articles/cowboy-2.0.0/index.html4
-rw-r--r--articles/cowboy-2.1.0/index.html4
-rw-r--r--articles/cowboy-2.2.0/index.html4
-rw-r--r--articles/cowboy-2.3.0/index.html4
-rw-r--r--articles/cowboy-2.4.0/index.html4
-rw-r--r--articles/cowboy-2.5.0/index.html4
-rw-r--r--articles/cowboy-2.6.0/index.html4
-rw-r--r--articles/cowboy-2.7.0/index.html4
-rw-r--r--articles/cowboy-2.8.0/index.html4
-rw-r--r--articles/cowboy-2.9.0/index.html4
-rw-r--r--articles/cowboy2-qs/index.html4
-rw-r--r--articles/dont-let-it-crash/index.html4
-rw-r--r--articles/erlang-meetup-10-septembre-2019/index.html4
-rw-r--r--articles/erlang-scalability/index.html4
-rw-r--r--articles/erlang-validate-utf8/index.html4
-rw-r--r--articles/erlang.mk-and-relx/index.html4
-rw-r--r--articles/erlanger-playbook-september-2015-update/index.html4
-rw-r--r--articles/erlanger-playbook/index.html4
-rw-r--r--articles/farwest-funded/index.html4
-rw-r--r--articles/github-sponsors/index.html4
-rw-r--r--articles/gun-1.0.0-rc.1/index.html4
-rw-r--r--articles/gun-1.0.0/index.html4
-rw-r--r--articles/gun-1.2.0/index.html4
-rw-r--r--articles/gun-1.3.0/index.html4
-rw-r--r--articles/gun-2.0.0-pre.1/index.html4
-rw-r--r--articles/gun-2.0.0-pre.2/index.html4
-rw-r--r--articles/gun-2.0.0-rc.1/index.html4
-rw-r--r--articles/gun-2.0.0/index.html355
-rw-r--r--articles/index.html38
-rw-r--r--articles/index.xml13
-rw-r--r--articles/january-2014-status/index.html4
-rw-r--r--articles/joe_the_rubber_duck/index.html4
-rw-r--r--articles/merry-christmas-2018/index.html4
-rw-r--r--articles/merry-christmas-2019/index.html4
-rw-r--r--articles/ml-archives/index.html4
-rw-r--r--articles/on-open-source/index.html4
-rw-r--r--articles/page/2/index.html38
-rw-r--r--articles/page/3/index.html18
-rw-r--r--articles/ranch-1.3/index.html4
-rw-r--r--articles/ranch-1.6.0/index.html4
-rw-r--r--articles/ranch-1.7.0/index.html4
-rw-r--r--articles/ranch-2.0.0-rc.1/index.html4
-rw-r--r--articles/ranch-2.0.0/index.html4
-rw-r--r--articles/ranch-2.1.0/index.html4
-rw-r--r--articles/ranch-ftp/index.html4
-rw-r--r--articles/the-elephant-in-the-room/index.html4
-rw-r--r--articles/the-gateway-trilogy/index.html4
-rw-r--r--articles/the-story-so-far/index.html4
-rw-r--r--articles/tictactoe/index.html4
-rw-r--r--articles/website-update/index.html4
-rw-r--r--articles/xerl-0.1-empty-modules/index.html4
-rw-r--r--articles/xerl-0.2-two-modules/index.html4
-rw-r--r--articles/xerl-0.3-atomic-expressions/index.html4
-rw-r--r--articles/xerl-0.4-expression-separator/index.html4
-rw-r--r--articles/xerl-0.5-intermediate-module/index.html4
-rw-r--r--docs/en/gun/2.0/guide/introduction.asciidoc2
-rw-r--r--docs/en/gun/2.0/guide/introduction/index.html2
-rw-r--r--docs/en/gun/2.0/guide/migrating_from_1.3.asciidoc43
-rw-r--r--docs/en/gun/2.0/guide/migrating_from_1.3/index.html22
-rw-r--r--docs/index.xml2
-rw-r--r--donate/index.html2
-rw-r--r--erlanger-playbook/index.html2
-rw-r--r--index.html4
-rw-r--r--index.xml13
-rw-r--r--services/index.html2
-rw-r--r--sitemap.xml7
72 files changed, 814 insertions, 49 deletions
diff --git a/_build/content/articles/gun-2.0.0.asciidoc b/_build/content/articles/gun-2.0.0.asciidoc
new file mode 100644
index 00000000..79720bd9
--- /dev/null
+++ b/_build/content/articles/gun-2.0.0.asciidoc
@@ -0,0 +1,80 @@
++++
+date = "2023-01-24T07:00:00+01:00"
+title = "Gun 2.0"
+
++++
+
+Gun `2.0.0` has been released!
+
+Gun 2.0 adds a ton of features along with a small number
+of breaking changes.
+
+Gun 2.0 includes state of the art tunnel support. With
+Gun 2.0 it is possible to make requests or data go through
+any number of proxy endpoints using any combination of
+TCP or TLS transports and HTTP/1.1, HTTP/2 or SOCKS5
+protocols. All combinations of the scenario Proxy1 ->
+Proxy2 -> Origin are tested and known to work.
+
+You can watch a demo of the tunnel support below. This
+video is the first of its kind. If you like it, or you
+don't like it, please tell me! I intend to continue
+producing those on a semi-regular basis. Watch:
+
+++++
+<video src="/res/gun2_unlimited_proxy_demo.webm" controls
+ width="640" height="360">
+</video>
+++++
+
+Gun 2.0 can now be used to send and receive raw data,
+as if it was just a normal socket. This can be
+useful when needing to connect through a number
+of HTTP/SOCKS5 proxies, allowing the use of Gun's
+great proxying capabilities for non-Web protocols.
+This can also be useful when performing HTTP/1.1
+Upgrade to custom protocols.
+
+Gun 2.0 adds many more features such as Websocket over
+HTTP/2, Websocket protocol negotiation, a built-in
+cookie store, graceful shutdown, flow control for
+data messages, event handlers and more.
+
+Gun 2.0 greatly improves the HTTP/2 performance when it
+comes to receiving large response bodies; and when receiving
+response bodies from many separate requests concurrently.
+
+Gun 2.0 will be more responsive in the event of connection
+failures. It now checks return values from send calls and
+has send timeouts enabled by default. For HTTP/2 a new
+option allows Gun to drop the connection when pings do
+not get a response in a timely manner.
+
+Gun now shares much of its HTTP/2 code with Cowboy,
+including the HTTP/2 state machine. Numerous issues were
+fixed as a result because the Cowboy implementation was
+much more advanced.
+
+The Gun connection process is now implemented using `gen_statem`.
+
+The `gun_pool` module is a significant experimental feature
+that allows users to create pools of connections. Pools
+are split by authority and a user-provided token, allowing
+users to reuse connections in a similar way to what Web
+browsers are doing. Please check it out and provide feedback!
+
+Gun 2.0 requires Erlang/OTP 22.0 or greater and is tested
+and supported on Linux, macOS and Windows.
+
+A complete
+list of changes can be found in the migration guide:
+https://ninenines.eu/docs/en/gun/2.0/guide/migrating_from_1.3/[Migrating from Gun 1.3 to 2.0].
+
+I will now focus on implementing HTTP/3 and QUIC, first
+in Cowboy and then in Gun.
+
+You can donate to this project via
+https://github.com/sponsors/essen[GitHub Sponsors].
+
+As usual, feedback is appreciated, and issues or
+questions should be sent via Github tickets. Thanks!
diff --git a/_build/data/projects/gun.toml b/_build/data/projects/gun.toml
index 79280d82..a777d713 100644
--- a/_build/data/projects/gun.toml
+++ b/_build/data/projects/gun.toml
@@ -1,10 +1,10 @@
title = "Gun"
catchphrase = "The smoking gun of HTTP clients."
-description = "Asynchronous, always-connected client with support for HTTP/1.1, HTTP/2 and Websocket."
+description = "Asynchronous client with support for HTTP/1.1, HTTP/2, Websocket and more."
name = "gun"
repository = "https://github.com/ninenines/gun"
versions = ["2.0", "1.3", "1.2", "1.1", "1.0"]
-branches = ["master", "1.3.1", "1.2.0", "1.1.0", "1.0.0"]
+branches = ["2.0.0", "1.3.1", "1.2.0", "1.1.0", "1.0.0"]
has_source = true
has_guide = true
has_manual = true
diff --git a/articles/asciideck/index.html b/articles/asciideck/index.html
index 60a1708f..1ad52960 100644
--- a/articles/asciideck/index.html
+++ b/articles/asciideck/index.html
@@ -109,6 +109,10 @@ http://www.gnu.org/software/src-highlite -->
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/cowboy-2.0.0-pre.4/index.html b/articles/cowboy-2.0.0-pre.4/index.html
index a95b0f95..79741b77 100644
--- a/articles/cowboy-2.0.0-pre.4/index.html
+++ b/articles/cowboy-2.0.0-pre.4/index.html
@@ -128,6 +128,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/cowboy-2.0.0-rc.1/index.html b/articles/cowboy-2.0.0-rc.1/index.html
index 6aae6533..3920e1ea 100644
--- a/articles/cowboy-2.0.0-rc.1/index.html
+++ b/articles/cowboy-2.0.0-rc.1/index.html
@@ -99,6 +99,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/cowboy-2.0.0-rc.2/index.html b/articles/cowboy-2.0.0-rc.2/index.html
index e3e017cb..280688cf 100644
--- a/articles/cowboy-2.0.0-rc.2/index.html
+++ b/articles/cowboy-2.0.0-rc.2/index.html
@@ -92,6 +92,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/cowboy-2.0.0/index.html b/articles/cowboy-2.0.0/index.html
index a7aaa2db..c47ec919 100644
--- a/articles/cowboy-2.0.0/index.html
+++ b/articles/cowboy-2.0.0/index.html
@@ -98,6 +98,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/cowboy-2.1.0/index.html b/articles/cowboy-2.1.0/index.html
index bf8164da..ae0af495 100644
--- a/articles/cowboy-2.1.0/index.html
+++ b/articles/cowboy-2.1.0/index.html
@@ -95,6 +95,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/cowboy-2.2.0/index.html b/articles/cowboy-2.2.0/index.html
index da01e9f5..021c4781 100644
--- a/articles/cowboy-2.2.0/index.html
+++ b/articles/cowboy-2.2.0/index.html
@@ -93,6 +93,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/cowboy-2.3.0/index.html b/articles/cowboy-2.3.0/index.html
index 5cdf603f..64a0c76d 100644
--- a/articles/cowboy-2.3.0/index.html
+++ b/articles/cowboy-2.3.0/index.html
@@ -85,6 +85,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/cowboy-2.4.0/index.html b/articles/cowboy-2.4.0/index.html
index 21494ef5..3d0027a8 100644
--- a/articles/cowboy-2.4.0/index.html
+++ b/articles/cowboy-2.4.0/index.html
@@ -87,6 +87,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/cowboy-2.5.0/index.html b/articles/cowboy-2.5.0/index.html
index f251fef9..707d1d6d 100644
--- a/articles/cowboy-2.5.0/index.html
+++ b/articles/cowboy-2.5.0/index.html
@@ -91,6 +91,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/cowboy-2.6.0/index.html b/articles/cowboy-2.6.0/index.html
index 84e340f7..a9131a16 100644
--- a/articles/cowboy-2.6.0/index.html
+++ b/articles/cowboy-2.6.0/index.html
@@ -88,6 +88,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/cowboy-2.7.0/index.html b/articles/cowboy-2.7.0/index.html
index d6398dce..8f5b7c05 100644
--- a/articles/cowboy-2.7.0/index.html
+++ b/articles/cowboy-2.7.0/index.html
@@ -89,6 +89,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/cowboy-2.8.0/index.html b/articles/cowboy-2.8.0/index.html
index bee4f587..81752a81 100644
--- a/articles/cowboy-2.8.0/index.html
+++ b/articles/cowboy-2.8.0/index.html
@@ -88,6 +88,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/cowboy-2.9.0/index.html b/articles/cowboy-2.9.0/index.html
index d355b58d..cf7e4521 100644
--- a/articles/cowboy-2.9.0/index.html
+++ b/articles/cowboy-2.9.0/index.html
@@ -87,6 +87,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/cowboy2-qs/index.html b/articles/cowboy2-qs/index.html
index 234fe0d5..2e9af5e5 100644
--- a/articles/cowboy2-qs/index.html
+++ b/articles/cowboy2-qs/index.html
@@ -129,6 +129,10 @@ http://www.gnu.org/software/src-highlite -->
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/dont-let-it-crash/index.html b/articles/dont-let-it-crash/index.html
index 2ff5ce37..46377706 100644
--- a/articles/dont-let-it-crash/index.html
+++ b/articles/dont-let-it-crash/index.html
@@ -104,6 +104,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/erlang-meetup-10-septembre-2019/index.html b/articles/erlang-meetup-10-septembre-2019/index.html
index 74bfa4b3..c0d939d5 100644
--- a/articles/erlang-meetup-10-septembre-2019/index.html
+++ b/articles/erlang-meetup-10-septembre-2019/index.html
@@ -84,6 +84,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/erlang-scalability/index.html b/articles/erlang-scalability/index.html
index 80bfb622..2570eca2 100644
--- a/articles/erlang-scalability/index.html
+++ b/articles/erlang-scalability/index.html
@@ -116,6 +116,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/erlang-validate-utf8/index.html b/articles/erlang-validate-utf8/index.html
index c36466fe..58909037 100644
--- a/articles/erlang-validate-utf8/index.html
+++ b/articles/erlang-validate-utf8/index.html
@@ -232,6 +232,10 @@ http://www.gnu.org/software/src-highlite -->
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/erlang.mk-and-relx/index.html b/articles/erlang.mk-and-relx/index.html
index 1f1ffa2e..3a61fe7b 100644
--- a/articles/erlang.mk-and-relx/index.html
+++ b/articles/erlang.mk-and-relx/index.html
@@ -118,6 +118,10 @@ cowboy-0.8.5 erlydtl-0.7.0 ninenines-0.2.0 stdlib-1.19.1</pre></div></div>
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/erlanger-playbook-september-2015-update/index.html b/articles/erlanger-playbook-september-2015-update/index.html
index 26d53bb9..47432860 100644
--- a/articles/erlanger-playbook-september-2015-update/index.html
+++ b/articles/erlanger-playbook-september-2015-update/index.html
@@ -87,6 +87,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/erlanger-playbook/index.html b/articles/erlanger-playbook/index.html
index 51f49fc9..6ab64aeb 100644
--- a/articles/erlanger-playbook/index.html
+++ b/articles/erlanger-playbook/index.html
@@ -128,6 +128,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/farwest-funded/index.html b/articles/farwest-funded/index.html
index 8e61b935..d95a3b5e 100644
--- a/articles/farwest-funded/index.html
+++ b/articles/farwest-funded/index.html
@@ -88,6 +88,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/github-sponsors/index.html b/articles/github-sponsors/index.html
index 697d4a47..3ed48066 100644
--- a/articles/github-sponsors/index.html
+++ b/articles/github-sponsors/index.html
@@ -85,6 +85,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/gun-1.0.0-rc.1/index.html b/articles/gun-1.0.0-rc.1/index.html
index 44a60f9c..283f1463 100644
--- a/articles/gun-1.0.0-rc.1/index.html
+++ b/articles/gun-1.0.0-rc.1/index.html
@@ -89,6 +89,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/gun-1.0.0/index.html b/articles/gun-1.0.0/index.html
index 6b3ea5f1..35b35ec0 100644
--- a/articles/gun-1.0.0/index.html
+++ b/articles/gun-1.0.0/index.html
@@ -88,6 +88,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/gun-1.2.0/index.html b/articles/gun-1.2.0/index.html
index 20eb9597..906c2143 100644
--- a/articles/gun-1.2.0/index.html
+++ b/articles/gun-1.2.0/index.html
@@ -88,6 +88,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/gun-1.3.0/index.html b/articles/gun-1.3.0/index.html
index bff135f3..5a7342a2 100644
--- a/articles/gun-1.3.0/index.html
+++ b/articles/gun-1.3.0/index.html
@@ -86,6 +86,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/gun-2.0.0-pre.1/index.html b/articles/gun-2.0.0-pre.1/index.html
index af0f8a54..97925295 100644
--- a/articles/gun-2.0.0-pre.1/index.html
+++ b/articles/gun-2.0.0-pre.1/index.html
@@ -93,6 +93,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/gun-2.0.0-pre.2/index.html b/articles/gun-2.0.0-pre.2/index.html
index b82636fd..afe588ed 100644
--- a/articles/gun-2.0.0-pre.2/index.html
+++ b/articles/gun-2.0.0-pre.2/index.html
@@ -91,6 +91,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/gun-2.0.0-rc.1/index.html b/articles/gun-2.0.0-rc.1/index.html
index 9f9b12f2..a34c37b3 100644
--- a/articles/gun-2.0.0-rc.1/index.html
+++ b/articles/gun-2.0.0-rc.1/index.html
@@ -96,6 +96,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/gun-2.0.0/index.html b/articles/gun-2.0.0/index.html
new file mode 100644
index 00000000..87a52979
--- /dev/null
+++ b/articles/gun-2.0.0/index.html
@@ -0,0 +1,355 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" content="">
+ <meta name="author" content="Loïc Hoguin based on a design from (Soft10) Pol Cámara">
+
+ <title>Nine Nines: Gun 2.0</title>
+
+ <link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700,400italic' rel='stylesheet' type='text/css'>
+ <link href="/css/99s.css?r=7" rel="stylesheet">
+
+ <link rel="shortcut icon" href="/img/ico/favicon.ico">
+ <link rel="apple-touch-icon-precomposed" sizes="114x114" href="/img/ico/apple-touch-icon-114.png">
+ <link rel="apple-touch-icon-precomposed" sizes="72x72" href="/img/ico/apple-touch-icon-72.png">
+ <link rel="apple-touch-icon-precomposed" href="/img/ico/apple-touch-icon-57.png">
+
+ </head>
+
+
+<body class="">
+ <header id="page-head">
+ <div id="topbar" class="container">
+ <div class="row">
+ <div class="span2">
+ <h1 id="logo"><a href="/" title="99s">99s</a></h1>
+ </div>
+ <div class="span10">
+
+ <div id="side-header">
+ <nav>
+ <ul>
+ <li class="active"><a title="Hear my thoughts" href="/articles">Articles</a></li>
+ <li><a title="Watch my talks" href="/talks">Talks</a></li>
+ <li><a title="Read the docs" href="/docs">Documentation</a></li>
+ <li><a title="Request my services" href="/services">Consulting & Training</a></li>
+ </ul>
+ </nav>
+ <ul id="social">
+ <li>
+ <a href="https://github.com/ninenines" title="Check my Github repositories"><img src="/img/ico_github.png" data-hover="/img/ico_github_alt.png" alt="Github"></a>
+ </li>
+ <li>
+ <a title="Contact me" href="mailto:[email protected]"><img src="/img/ico_mail.png" data-hover="/img/ico_mail_alt.png"></a>
+ </li>
+ </ul>
+ </div>
+ </div>
+ </div>
+ </div>
+
+
+</header>
+
+<div id="contents">
+<div class="container">
+<div class="row">
+<div class="span9 maincol">
+
+<article class="blog_item">
+<header>
+ <h1 class="lined-header"><span>Gun 2.0</span></h1>
+ <p class="date">
+ <span class="year">2023</span>
+ <span class="day-month">24 Jan</span>
+ </p>
+</header>
+
+<p>Gun <code>2.0.0</code> has been released!</p>
+<p>Gun 2.0 adds a ton of features along with a small number of breaking changes.</p>
+<p>Gun 2.0 includes state of the art tunnel support. With Gun 2.0 it is possible to make requests or data go through any number of proxy endpoints using any combination of TCP or TLS transports and HTTP/1.1, HTTP/2 or SOCKS5 protocols. All combinations of the scenario Proxy1 -&gt; Proxy2 -&gt; Origin are tested and known to work.</p>
+<p>You can watch a demo of the tunnel support below. This video is the first of its kind. If you like it, or you don&apos;t like it, please tell me! I intend to continue producing those on a semi-regular basis. Watch:</p>
+<video src="/res/gun2_unlimited_proxy_demo.webm" controls
+ width="640" height="360">
+</video><p>Gun 2.0 can now be used to send and receive raw data, as if it was just a normal socket. This can be useful when needing to connect through a number of HTTP/SOCKS5 proxies, allowing the use of Gun&apos;s great proxying capabilities for non-Web protocols. This can also be useful when performing HTTP/1.1 Upgrade to custom protocols.</p>
+<p>Gun 2.0 adds many more features such as Websocket over HTTP/2, Websocket protocol negotiation, a built-in cookie store, graceful shutdown, flow control for data messages, event handlers and more.</p>
+<p>Gun 2.0 greatly improves the HTTP/2 performance when it comes to receiving large response bodies; and when receiving response bodies from many separate requests concurrently.</p>
+<p>Gun 2.0 will be more responsive in the event of connection failures. It now checks return values from send calls and has send timeouts enabled by default. For HTTP/2 a new option allows Gun to drop the connection when pings do not get a response in a timely manner.</p>
+<p>Gun now shares much of its HTTP/2 code with Cowboy, including the HTTP/2 state machine. Numerous issues were fixed as a result because the Cowboy implementation was much more advanced.</p>
+<p>The Gun connection process is now implemented using <code>gen_statem</code>.</p>
+<p>The <code>gun_pool</code> module is a significant experimental feature that allows users to create pools of connections. Pools are split by authority and a user-provided token, allowing users to reuse connections in a similar way to what Web browsers are doing. Please check it out and provide feedback!</p>
+<p>Gun 2.0 requires Erlang/OTP 22.0 or greater and is tested and supported on Linux, macOS and Windows.</p>
+<p>A complete list of changes can be found in the migration guide: <a href="https://ninenines.eu/docs/en/gun/2.0/guide/migrating_from_1.3/">Migrating from Gun 1.3 to 2.0</a>.</p>
+<p>I will now focus on implementing HTTP/3 and QUIC, first in Cowboy and then in Gun.</p>
+<p>You can donate to this project via <a href="https://github.com/sponsors/essen">GitHub Sponsors</a>.</p>
+<p>As usual, feedback is appreciated, and issues or questions should be sent via Github tickets. Thanks!</p>
+
+
+</article>
+</div>
+
+<div class="span3 sidecol">
+<h3>More articles</h3>
+<ul id="articles-nav" class="extra_margin">
+
+
+
+
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/cowboy-2.9.0/">Cowboy 2.9</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0-rc.1/">Gun 2.0 release candidate 1</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/ranch-2.0.0/">Ranch 2.0</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/cowboy-2.8.0/">Cowboy 2.8</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/the-gateway-trilogy/">The Gateway Trilogy</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0-pre.2/">Gun 2.0 pre-release 2</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/merry-christmas-2019/">Merry Christmas 2019: New Beginnings</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/github-sponsors/">GitHub Sponsors</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/cowboy-2.7.0/">Cowboy 2.7</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0-pre.1/">Gun 2.0 pre-release 1</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/erlang-meetup-10-septembre-2019/">Erlang meetup: 10 septembre 2019</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/ranch-2.0.0-rc.1/">Ranch 2.0 release candidate 1</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/joe_the_rubber_duck/">Joe Armstrong the rubber duck</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/merry-christmas-2018/">Merry Christmas 2018: A Recap</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/cowboy-2.6.0/">Cowboy 2.6</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/ranch-1.7.0/">Ranch 1.7</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/cowboy-2.5.0/">Cowboy 2.5</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/gun-1.3.0/">Gun 1.3</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/gun-1.2.0/">Gun 1.2</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/ranch-1.6.0/">Ranch 1.6</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/gun-1.0.0/">Gun 1.0</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/asciideck/">Asciideck: Asciidoc for Erlang</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/gun-1.0.0-rc.1/">Gun 1.0 release candidate 1</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/cowboy-2.4.0/">Cowboy 2.4</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/cowboy-2.3.0/">Cowboy 2.3</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/cowboy-2.2.0/">Cowboy 2.2</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/cowboy-2.1.0/">Cowboy 2.1</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/cowboy-2.0.0/">Cowboy 2.0</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/cowboy-2.0.0-rc.2/">Cowboy 2.0 release candidate 2</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/cowboy-2.0.0-rc.1/">Cowboy 2.0 release candidate 1</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/the-elephant-in-the-room/">The elephant in the room</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/dont-let-it-crash/">Don&#39;t let it crash</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/cowboy-2.0.0-pre.4/">Cowboy 2.0 pre-release 4</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/ranch-1.3/">Ranch 1.3</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/ml-archives/">Mailing list archived</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/website-update/">Website update</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/erlanger-playbook-september-2015-update/">The Erlanger Playbook September 2015 Update</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/erlanger-playbook/">The Erlanger Playbook</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/erlang-validate-utf8/">Validating UTF-8 binaries with Erlang</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/on-open-source/">On open source</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/the-story-so-far/">The story so far</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/cowboy2-qs/">Cowboy 2.0 and query strings</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/january-2014-status/">January 2014 status</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/farwest-funded/">Farwest got funded!</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/erlang.mk-and-relx/">Build Erlang releases with Erlang.mk and Relx</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/xerl-0.5-intermediate-module/">Xerl: intermediate module</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/xerl-0.4-expression-separator/">Xerl: expression separator</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/erlang-scalability/">Erlang Scalability</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/xerl-0.3-atomic-expressions/">Xerl: atomic expressions</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/xerl-0.2-two-modules/">Xerl: two modules</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/xerl-0.1-empty-modules/">Xerl: empty modules</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/ranch-ftp/">Build an FTP Server with Ranch in 30 Minutes</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/tictactoe/">Erlang Tic Tac Toe</a></li>
+
+
+</ul>
+
+<h3>Feedback</h3>
+<p>Feel free to <a href="mailto:[email protected]">email us</a>
+if you found any mistake or need clarification on any of the
+articles.</p>
+
+</div>
+</div>
+</div>
+</div>
+
+ <footer>
+ <div class="container">
+ <div class="row">
+ <div class="span6">
+ <p id="scroll-top"><a href="#">↑ Scroll to top</a></p>
+ <nav>
+ <ul>
+ <li><a href="mailto:[email protected]" title="Contact us">Contact us</a></li><li><a href="https://github.com/ninenines/ninenines.github.io" title="Github repository">Contribute to this site</a></li>
+ </ul>
+ </nav>
+ </div>
+ <div class="span6 credits">
+ <p><img src="/img/footer_logo.png"></p>
+ <p>Copyright &copy; Loïc Hoguin 2012-2018</p>
+ </div>
+ </div>
+ </div>
+ </footer>
+
+
+ <script src="/js/custom.js"></script>
+ </body>
+</html>
+
diff --git a/articles/index.html b/articles/index.html
index 7fc81f6f..8911e938 100644
--- a/articles/index.html
+++ b/articles/index.html
@@ -65,6 +65,24 @@
<article class="blog_item">
<header>
+ <h2><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></h2>
+ <p class="date">
+ <span class="year">2023</span>
+ <span class="day-month">24 Jan</span>
+ </p>
+ </header>
+
+ <p>Gun 2.0.0 has been released!
+Gun 2.0 adds a ton of features along with a small number of breaking changes.
+Gun 2.0 includes state of the art tunnel support. With Gun 2.0 it is possible to make requests or data go through any number of proxy endpoints using any combination of TCP or TLS transports and HTTP/1.1, HTTP/2 or SOCKS5 protocols. All combinations of the scenario Proxy1 -&gt; Proxy2 -&gt; Origin are tested and known to work.</p>
+
+ <p style="text-align:right">
+ <a class="read_more" href="https://ninenines.eu/articles/gun-2.0.0/">Read More</a>
+ </p>
+ </article>
+
+ <article class="blog_item">
+ <header>
<h2><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></h2>
<p class="date">
<span class="year">2021</span>
@@ -411,26 +429,6 @@ You can donate to this project via GitHub Sponsors. These funds are used to pay
</p>
</article>
- <article class="blog_item">
- <header>
- <h2><a href="https://ninenines.eu/articles/gun-1.2.0/">Gun 1.2</a></h2>
- <p class="date">
- <span class="year">2018</span>
- <span class="day-month">17 Sep</span>
- </p>
- </header>
-
- <p>Gun 1.2.0 has been released!
-Gun is an HTTP/1.1, HTTP/2 and Websocket client for Erlang/OTP.
-Gun now supports issuing CONNECT requests to HTTP proxies in order to establish tunnels to origin servers. Gun can establish tunnels over one or more proxies as necessary.
-All existing protocols can be used inside the tunnel, including HTTP/1.1, HTTP/2 and Websocket over both TCP and TLS connections.
-Note that it is currently not possible to tunnel a TLS connection via an HTTPS proxy due to limitations in the current version of Erlang/OTP.</p>
-
- <p style="text-align:right">
- <a class="read_more" href="https://ninenines.eu/articles/gun-1.2.0/">Read More</a>
- </p>
- </article>
-
<nav class="pagination" role="pagination">
diff --git a/articles/index.xml b/articles/index.xml
index 575b231d..7ca0ca68 100644
--- a/articles/index.xml
+++ b/articles/index.xml
@@ -6,12 +6,23 @@
<description>Recent content in Articles on Nine Nines</description>
<generator>Hugo -- gohugo.io</generator>
<language>en-us</language>
- <lastBuildDate>Thu, 09 Sep 2021 07:00:00 +0100</lastBuildDate>
+ <lastBuildDate>Tue, 24 Jan 2023 07:00:00 +0100</lastBuildDate>
<atom:link href="https://ninenines.eu/articles/index.xml" rel="self" type="application/rss+xml" />
<item>
+ <title>Gun 2.0</title>
+ <link>https://ninenines.eu/articles/gun-2.0.0/</link>
+ <pubDate>Tue, 24 Jan 2023 07:00:00 +0100</pubDate>
+
+ <guid>https://ninenines.eu/articles/gun-2.0.0/</guid>
+ <description>Gun 2.0.0 has been released!
+Gun 2.0 adds a ton of features along with a small number of breaking changes.
+Gun 2.0 includes state of the art tunnel support. With Gun 2.0 it is possible to make requests or data go through any number of proxy endpoints using any combination of TCP or TLS transports and HTTP/1.1, HTTP/2 or SOCKS5 protocols. All combinations of the scenario Proxy1 -&amp;gt; Proxy2 -&amp;gt; Origin are tested and known to work.</description>
+ </item>
+
+ <item>
<title>Ranch 2.1</title>
<link>https://ninenines.eu/articles/ranch-2.1.0/</link>
<pubDate>Thu, 09 Sep 2021 07:00:00 +0100</pubDate>
diff --git a/articles/january-2014-status/index.html b/articles/january-2014-status/index.html
index 64bb8e19..3c571fe5 100644
--- a/articles/january-2014-status/index.html
+++ b/articles/january-2014-status/index.html
@@ -114,6 +114,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/joe_the_rubber_duck/index.html b/articles/joe_the_rubber_duck/index.html
index c12df396..2f76e1ed 100644
--- a/articles/joe_the_rubber_duck/index.html
+++ b/articles/joe_the_rubber_duck/index.html
@@ -88,6 +88,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/merry-christmas-2018/index.html b/articles/merry-christmas-2018/index.html
index f10f1f10..9ab74e00 100644
--- a/articles/merry-christmas-2018/index.html
+++ b/articles/merry-christmas-2018/index.html
@@ -95,6 +95,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/merry-christmas-2019/index.html b/articles/merry-christmas-2019/index.html
index c2e8c0d1..292b6059 100644
--- a/articles/merry-christmas-2019/index.html
+++ b/articles/merry-christmas-2019/index.html
@@ -91,6 +91,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/ml-archives/index.html b/articles/ml-archives/index.html
index f5a1b4f5..96b0badf 100644
--- a/articles/ml-archives/index.html
+++ b/articles/ml-archives/index.html
@@ -85,6 +85,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/on-open-source/index.html b/articles/on-open-source/index.html
index cbaef88d..a017e6e9 100644
--- a/articles/on-open-source/index.html
+++ b/articles/on-open-source/index.html
@@ -97,6 +97,10 @@ much left to look at today</a>. This was followed by a <a href="https://github.c
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/page/2/index.html b/articles/page/2/index.html
index 1d36cb20..a5da7537 100644
--- a/articles/page/2/index.html
+++ b/articles/page/2/index.html
@@ -65,6 +65,26 @@
<article class="blog_item">
<header>
+ <h2><a href="https://ninenines.eu/articles/gun-1.2.0/">Gun 1.2</a></h2>
+ <p class="date">
+ <span class="year">2018</span>
+ <span class="day-month">17 Sep</span>
+ </p>
+ </header>
+
+ <p>Gun 1.2.0 has been released!
+Gun is an HTTP/1.1, HTTP/2 and Websocket client for Erlang/OTP.
+Gun now supports issuing CONNECT requests to HTTP proxies in order to establish tunnels to origin servers. Gun can establish tunnels over one or more proxies as necessary.
+All existing protocols can be used inside the tunnel, including HTTP/1.1, HTTP/2 and Websocket over both TCP and TLS connections.
+Note that it is currently not possible to tunnel a TLS connection via an HTTPS proxy due to limitations in the current version of Erlang/OTP.</p>
+
+ <p style="text-align:right">
+ <a class="read_more" href="https://ninenines.eu/articles/gun-1.2.0/">Read More</a>
+ </p>
+ </article>
+
+ <article class="blog_item">
+ <header>
<h2><a href="https://ninenines.eu/articles/ranch-1.6.0/">Ranch 1.6</a></h2>
<p class="date">
<span class="year">2018</span>
@@ -414,24 +434,6 @@ About this book; Changelog; Future additions Erlang: Building blocks; Patterns
</p>
</article>
- <article class="blog_item">
- <header>
- <h2><a href="https://ninenines.eu/articles/erlang-validate-utf8/">Validating UTF-8 binaries with Erlang</a></h2>
- <p class="date">
- <span class="year">2015</span>
- <span class="day-month">06 Mar</span>
- </p>
- </header>
-
- <p>Yesterday I pushed Websocket permessage-deflate to Cowboy master. I also pushed a change in the way the code validates UTF-8 data (required for text and close frames as per the spec).
-When looking into why the permessage-deflate tests in autobahntestsuite were taking such a long time, I found that autobahn is using an adaptation of the algorithm named Flexible and Economical UTF-8 Decoder. This is the C99 implementation:
-// Copyright (c) 2008-2009 Bjoern Hoehrmann &lt;bjoern@hoehrmann.</p>
-
- <p style="text-align:right">
- <a class="read_more" href="https://ninenines.eu/articles/erlang-validate-utf8/">Read More</a>
- </p>
- </article>
-
<nav class="pagination" role="pagination">
diff --git a/articles/page/3/index.html b/articles/page/3/index.html
index f0ffdf0f..fd007219 100644
--- a/articles/page/3/index.html
+++ b/articles/page/3/index.html
@@ -65,6 +65,24 @@
<article class="blog_item">
<header>
+ <h2><a href="https://ninenines.eu/articles/erlang-validate-utf8/">Validating UTF-8 binaries with Erlang</a></h2>
+ <p class="date">
+ <span class="year">2015</span>
+ <span class="day-month">06 Mar</span>
+ </p>
+ </header>
+
+ <p>Yesterday I pushed Websocket permessage-deflate to Cowboy master. I also pushed a change in the way the code validates UTF-8 data (required for text and close frames as per the spec).
+When looking into why the permessage-deflate tests in autobahntestsuite were taking such a long time, I found that autobahn is using an adaptation of the algorithm named Flexible and Economical UTF-8 Decoder. This is the C99 implementation:
+// Copyright (c) 2008-2009 Bjoern Hoehrmann &lt;bjoern@hoehrmann.</p>
+
+ <p style="text-align:right">
+ <a class="read_more" href="https://ninenines.eu/articles/erlang-validate-utf8/">Read More</a>
+ </p>
+ </article>
+
+ <article class="blog_item">
+ <header>
<h2><a href="https://ninenines.eu/articles/on-open-source/">On open source</a></h2>
<p class="date">
<span class="year">2014</span>
diff --git a/articles/ranch-1.3/index.html b/articles/ranch-1.3/index.html
index 1d9e6635..f6548e48 100644
--- a/articles/ranch-1.3/index.html
+++ b/articles/ranch-1.3/index.html
@@ -126,6 +126,10 @@ Primary key fingerprint<font color="#990000">:</font> F19F 189C ECC7 <font color
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/ranch-1.6.0/index.html b/articles/ranch-1.6.0/index.html
index 7587f5e8..a4cb2ea9 100644
--- a/articles/ranch-1.6.0/index.html
+++ b/articles/ranch-1.6.0/index.html
@@ -88,6 +88,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/ranch-1.7.0/index.html b/articles/ranch-1.7.0/index.html
index b9d9df55..3da114e7 100644
--- a/articles/ranch-1.7.0/index.html
+++ b/articles/ranch-1.7.0/index.html
@@ -87,6 +87,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/ranch-2.0.0-rc.1/index.html b/articles/ranch-2.0.0-rc.1/index.html
index 9184f550..8139b030 100644
--- a/articles/ranch-2.0.0-rc.1/index.html
+++ b/articles/ranch-2.0.0-rc.1/index.html
@@ -96,6 +96,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/ranch-2.0.0/index.html b/articles/ranch-2.0.0/index.html
index 1529c89e..5e378bc8 100644
--- a/articles/ranch-2.0.0/index.html
+++ b/articles/ranch-2.0.0/index.html
@@ -95,6 +95,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/ranch-2.1.0/index.html b/articles/ranch-2.1.0/index.html
index 56717a13..5b050d8b 100644
--- a/articles/ranch-2.1.0/index.html
+++ b/articles/ranch-2.1.0/index.html
@@ -90,6 +90,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/ranch-ftp/index.html b/articles/ranch-ftp/index.html
index 173b6460..bda3b161 100644
--- a/articles/ranch-ftp/index.html
+++ b/articles/ranch-ftp/index.html
@@ -228,6 +228,10 @@ http://www.gnu.org/software/src-highlite -->
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/the-elephant-in-the-room/index.html b/articles/the-elephant-in-the-room/index.html
index dda1a024..1eb5b519 100644
--- a/articles/the-elephant-in-the-room/index.html
+++ b/articles/the-elephant-in-the-room/index.html
@@ -110,6 +110,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/the-gateway-trilogy/index.html b/articles/the-gateway-trilogy/index.html
index c5d6e3dd..1abd47c2 100644
--- a/articles/the-gateway-trilogy/index.html
+++ b/articles/the-gateway-trilogy/index.html
@@ -85,6 +85,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/the-story-so-far/index.html b/articles/the-story-so-far/index.html
index 9d6a1873..155d9197 100644
--- a/articles/the-story-so-far/index.html
+++ b/articles/the-story-so-far/index.html
@@ -101,6 +101,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/tictactoe/index.html b/articles/tictactoe/index.html
index 5cd7419c..86bce465 100644
--- a/articles/tictactoe/index.html
+++ b/articles/tictactoe/index.html
@@ -133,6 +133,10 @@ http://www.gnu.org/software/src-highlite -->
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/website-update/index.html b/articles/website-update/index.html
index cea314c2..2a754b6b 100644
--- a/articles/website-update/index.html
+++ b/articles/website-update/index.html
@@ -90,6 +90,10 @@
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/xerl-0.1-empty-modules/index.html b/articles/xerl-0.1-empty-modules/index.html
index bc9ae3ac..e2d295ab 100644
--- a/articles/xerl-0.1-empty-modules/index.html
+++ b/articles/xerl-0.1-empty-modules/index.html
@@ -168,6 +168,10 @@ http://www.gnu.org/software/src-highlite -->
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/xerl-0.2-two-modules/index.html b/articles/xerl-0.2-two-modules/index.html
index 6f1e5a7c..6841fc3f 100644
--- a/articles/xerl-0.2-two-modules/index.html
+++ b/articles/xerl-0.2-two-modules/index.html
@@ -196,6 +196,10 @@ http://www.gnu.org/software/src-highlite -->
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/xerl-0.3-atomic-expressions/index.html b/articles/xerl-0.3-atomic-expressions/index.html
index 360077c7..c581c18e 100644
--- a/articles/xerl-0.3-atomic-expressions/index.html
+++ b/articles/xerl-0.3-atomic-expressions/index.html
@@ -165,6 +165,10 @@ http://www.gnu.org/software/src-highlite -->
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/xerl-0.4-expression-separator/index.html b/articles/xerl-0.4-expression-separator/index.html
index a534cf9a..92640e02 100644
--- a/articles/xerl-0.4-expression-separator/index.html
+++ b/articles/xerl-0.4-expression-separator/index.html
@@ -117,6 +117,10 @@ http://www.gnu.org/software/src-highlite -->
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/articles/xerl-0.5-intermediate-module/index.html b/articles/xerl-0.5-intermediate-module/index.html
index 799b39b2..db141c74 100644
--- a/articles/xerl-0.5-intermediate-module/index.html
+++ b/articles/xerl-0.5-intermediate-module/index.html
@@ -161,6 +161,10 @@ http://www.gnu.org/software/src-highlite -->
+ <li><a href="https://ninenines.eu/articles/gun-2.0.0/">Gun 2.0</a></li>
+
+
+
<li><a href="https://ninenines.eu/articles/ranch-2.1.0/">Ranch 2.1</a></li>
diff --git a/docs/en/gun/2.0/guide/introduction.asciidoc b/docs/en/gun/2.0/guide/introduction.asciidoc
index 097cf396..948dde95 100644
--- a/docs/en/gun/2.0/guide/introduction.asciidoc
+++ b/docs/en/gun/2.0/guide/introduction.asciidoc
@@ -21,7 +21,7 @@ Gun is developed for Erlang/OTP 22.0 and newer.
Gun uses the ISC License.
----
-Copyright (c) 2013-2020, Loïc Hoguin <[email protected]>
+Copyright (c) 2013-2023, Loïc Hoguin <[email protected]>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
diff --git a/docs/en/gun/2.0/guide/introduction/index.html b/docs/en/gun/2.0/guide/introduction/index.html
index 2035c5f3..be153533 100644
--- a/docs/en/gun/2.0/guide/introduction/index.html
+++ b/docs/en/gun/2.0/guide/introduction/index.html
@@ -70,7 +70,7 @@
<p>Gun is developed for Erlang/OTP 22.0 and newer.</p>
<h2 id="_license">License</h2>
<p>Gun uses the ISC License.</p>
-<div class="listingblock"><div class="content"><pre>Copyright (c) 2013-2020, Loïc Hoguin &lt;[email protected]&gt;
+<div class="listingblock"><div class="content"><pre>Copyright (c) 2013-2023, Loïc Hoguin &lt;[email protected]&gt;
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
diff --git a/docs/en/gun/2.0/guide/migrating_from_1.3.asciidoc b/docs/en/gun/2.0/guide/migrating_from_1.3.asciidoc
index 2e71a904..59f3381c 100644
--- a/docs/en/gun/2.0/guide/migrating_from_1.3.asciidoc
+++ b/docs/en/gun/2.0/guide/migrating_from_1.3.asciidoc
@@ -52,6 +52,12 @@ Gun 2.0 requires Erlang/OTP 22.0 or greater.
option controls how long we are willing to wait at most
before closing the connection.
+* Gun will better detect connection failures by checking the
+ return value from sending data to the socket. This applies
+ to all supported protocols. In addition, Gun now enables
+ `send_timeout_close` with a `send_timeout` value defaulting
+ to 15s.
+
* Flow control has been added. It allows limiting the number
of data/Websocket messages Gun sends to the calling process.
Gun will stop reading from the socket or stop updating the
@@ -107,6 +113,20 @@ Gun 2.0 requires Erlang/OTP 22.0 or greater.
improve performance or lower the memory usage, for
example.
+* A new `keepalive_tolerance` option for HTTP/2 enables
+ closing the connection automatically when ping acks
+ are not received in a timely manner. It nicely
+ complements the `keepalive` option that makes Gun
+ send pings.
+
+* Gun now supports Websocket subprotocol negotiation
+ and the feature is fully documented and tested.
+ This can be used to create handlers that will
+ implement a protocol from within the Gun process itself.
+ The negotiation is enabled by setting the `protocols`
+ setting. The `default_protocol` and `user_opts`
+ settings are also useful.
+
* It is now possible to send many Websocket frames in
a single `gun:ws_send/3` call.
@@ -139,7 +159,7 @@ Gun 2.0 requires Erlang/OTP 22.0 or greater.
(for example during state transitions when switching
protocols or connecting to proxies).
-* Update Cowlib to 2.11.0.
+* Update Cowlib to 2.12.0.
=== Experimental features added
@@ -286,3 +306,24 @@ Gun 2.0 requires Erlang/OTP 22.0 or greater.
* Fix a crash in gun:info/1 when the socket was closed before
we call Transport:sockname/1.
+
+* Fix flushing by stream reference. When the `gun_inform`
+ message was flushed the function would switch to flushing
+ all messages from the pid instead of only messages from
+ the given stream.
+
+* Allow setting a custom SNI value.
+
+* Fix double sending of last chunk in HTTP/1.1 when Gun is
+ asked to send empty data before closing the stream.
+
+* Gun will now properly ignore parameters when the media
+ type is text/event-stream.
+
+* Avoid noisy crashes in the TLS over TLS code.
+
+* Gun will now include the StreamRef of Websocket streams
+ when sending `gun_down` messages.
+
+* Gun will no longer reject HTTP proxies that use HTTP/1.0
+ for the version in their response.
diff --git a/docs/en/gun/2.0/guide/migrating_from_1.3/index.html b/docs/en/gun/2.0/guide/migrating_from_1.3/index.html
index 7c54aa6b..00d39fdc 100644
--- a/docs/en/gun/2.0/guide/migrating_from_1.3/index.html
+++ b/docs/en/gun/2.0/guide/migrating_from_1.3/index.html
@@ -73,6 +73,8 @@
</li>
<li>Graceful shutdown has been implemented. Graceful shutdown can be initiated on the client side by calling the new function <code>gun:shutdown/1</code> or when the owner process goes away; or on the peer side via the connection: close HTTP/1.1 header, the HTTP/2 GOAWAY frame or the Websocket close frame. Gun will try to complete existing streams when possible; other streams get canceled immediately. The <code>closing_timeout</code> option controls how long we are willing to wait at most before closing the connection.
</li>
+<li>Gun will better detect connection failures by checking the return value from sending data to the socket. This applies to all supported protocols. In addition, Gun now enables <code>send_timeout_close</code> with a <code>send_timeout</code> value defaulting to 15s.
+</li>
<li>Flow control has been added. It allows limiting the number of data/Websocket messages Gun sends to the calling process. Gun will stop reading from the socket or stop updating the protocol&apos;s flow control window when applicable as well, to apply some backpressure to the remote endpoint(s). It is disabled by default and can be applied on a per-request basis if necessary.
</li>
<li>An event handler interface has been added providing access to many internal Gun events. This can be used for a variety of purposes including logging, tracing or otherwise instrumenting a Gun connection.
@@ -95,6 +97,10 @@
</li>
<li>Many HTTP/2 options have been added, allowing great control over how Gun and the remote endpoint are using the HTTP/2 connection. They can be used to improve performance or lower the memory usage, for example.
</li>
+<li>A new <code>keepalive_tolerance</code> option for HTTP/2 enables closing the connection automatically when ping acks are not received in a timely manner. It nicely complements the <code>keepalive</code> option that makes Gun send pings.
+</li>
+<li>Gun now supports Websocket subprotocol negotiation and the feature is fully documented and tested. This can be used to create handlers that will implement a protocol from within the Gun process itself. The negotiation is enabled by setting the <code>protocols</code> setting. The <code>default_protocol</code> and <code>user_opts</code> settings are also useful.
+</li>
<li>It is now possible to send many Websocket frames in a single <code>gun:ws_send/3</code> call.
</li>
<li>Gun may now send Websocket ping frames automatically at intervals determined by the <code>keepalive</code> option. It is disabled by default.
@@ -111,7 +117,7 @@
</li>
<li>Many improvements have been done to postpone or reject requests and other operations while in the wrong state (for example during state transitions when switching protocols or connecting to proxies).
</li>
-<li>Update Cowlib to 2.11.0.
+<li>Update Cowlib to 2.12.0.
</li>
</ul>
<h2 id="_experimental_features_added">Experimental features added</h2>
@@ -197,6 +203,20 @@
</li>
<li>Fix a crash in gun:info/1 when the socket was closed before we call Transport:sockname/1.
</li>
+<li>Fix flushing by stream reference. When the <code>gun_inform</code> message was flushed the function would switch to flushing all messages from the pid instead of only messages from the given stream.
+</li>
+<li>Allow setting a custom SNI value.
+</li>
+<li>Fix double sending of last chunk in HTTP/1.1 when Gun is asked to send empty data before closing the stream.
+</li>
+<li>Gun will now properly ignore parameters when the media type is text/event-stream.
+</li>
+<li>Avoid noisy crashes in the TLS over TLS code.
+</li>
+<li>Gun will now include the StreamRef of Websocket streams when sending <code>gun_down</code> messages.
+</li>
+<li>Gun will no longer reject HTTP proxies that use HTTP/1.0 for the version in their response.
+</li>
</ul>
diff --git a/docs/index.xml b/docs/index.xml
index 4090aadc..34467a9e 100644
--- a/docs/index.xml
+++ b/docs/index.xml
@@ -82,7 +82,7 @@ Prerequisites Knowledge of Erlang, but also of the HTTP/1.1, HTTP/2 and Websocke
Supported platforms Gun is tested and supported on Linux, FreeBSD, Windows and OSX.
Gun is developed for Erlang/OTP 22.0 and newer.
License Gun uses the ISC License.
-Copyright (c) 2013-2020, Loïc Hoguin &amp;lt;[email protected]&amp;gt; Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.</description>
+Copyright (c) 2013-2023, Loïc Hoguin &amp;lt;[email protected]&amp;gt; Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.</description>
</item>
<item>
diff --git a/donate/index.html b/donate/index.html
index 25cef413..772c8c0d 100644
--- a/donate/index.html
+++ b/donate/index.html
@@ -777,6 +777,8 @@
+
+
<h3 id="_like_my_work__donate">Like my work? Donate!</h3>
<p>Donate to Loïc Hoguin because his work on Cowboy, Ranch, Gun and Erlang.mk is fantastic:</p>
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" style="display:inline">
diff --git a/erlanger-playbook/index.html b/erlanger-playbook/index.html
index ff26da97..93108c1c 100644
--- a/erlanger-playbook/index.html
+++ b/erlanger-playbook/index.html
@@ -817,6 +817,8 @@
+
+
<h3 id="_like_my_work__donate">Like my work? Donate!</h3>
<p>Donate to Loïc Hoguin because his work on Cowboy, Ranch, Gun and Erlang.mk is fantastic:</p>
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" style="display:inline">
diff --git a/index.html b/index.html
index beee6627..0cc3e509 100644
--- a/index.html
+++ b/index.html
@@ -169,7 +169,7 @@
<div class="span5">
<h1>Gun</h1>
<h2>The smoking gun of HTTP clients.</h2>
- <p>Asynchronous, always-connected client with support for HTTP/1.1, HTTP/2 and Websocket.</p>
+ <p>Asynchronous client with support for HTTP/1.1, HTTP/2, Websocket and more.</p>
<p class="right-buttons">
<a class="btn btn-large" href="https://github.com/ninenines/gun">Source Code</a>
@@ -917,6 +917,8 @@
+
+
<p>Reward my work via <a href="https://github.com/sponsors/essen">GitHub Sponsors</a> and<br/>GitHub will double the funds I receive!</p>
diff --git a/index.xml b/index.xml
index c7b4eabe..8a115708 100644
--- a/index.xml
+++ b/index.xml
@@ -83,7 +83,7 @@ Prerequisites Knowledge of Erlang, but also of the HTTP/1.1, HTTP/2 and Websocke
Supported platforms Gun is tested and supported on Linux, FreeBSD, Windows and OSX.
Gun is developed for Erlang/OTP 22.0 and newer.
License Gun uses the ISC License.
-Copyright (c) 2013-2020, Loïc Hoguin &amp;lt;[email protected]&amp;gt; Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.</description>
+Copyright (c) 2013-2023, Loïc Hoguin &amp;lt;[email protected]&amp;gt; Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.</description>
</item>
<item>
@@ -3345,6 +3345,17 @@ HTTP IANA Registries HTTP Method Registry HTTP Status Code Registry Message He
</item>
<item>
+ <title>Gun 2.0</title>
+ <link>https://ninenines.eu/articles/gun-2.0.0/</link>
+ <pubDate>Tue, 24 Jan 2023 07:00:00 +0100</pubDate>
+
+ <guid>https://ninenines.eu/articles/gun-2.0.0/</guid>
+ <description>Gun 2.0.0 has been released!
+Gun 2.0 adds a ton of features along with a small number of breaking changes.
+Gun 2.0 includes state of the art tunnel support. With Gun 2.0 it is possible to make requests or data go through any number of proxy endpoints using any combination of TCP or TLS transports and HTTP/1.1, HTTP/2 or SOCKS5 protocols. All combinations of the scenario Proxy1 -&amp;gt; Proxy2 -&amp;gt; Origin are tested and known to work.</description>
+ </item>
+
+ <item>
<title>Ranch 2.1</title>
<link>https://ninenines.eu/articles/ranch-2.1.0/</link>
<pubDate>Thu, 09 Sep 2021 07:00:00 +0100</pubDate>
diff --git a/services/index.html b/services/index.html
index 745044fb..6a5592d3 100644
--- a/services/index.html
+++ b/services/index.html
@@ -803,6 +803,8 @@
+
+
<h3 id="_like_my_work__donate">Like my work? Donate!</h3>
<p>Donate to Loïc Hoguin because his work on Cowboy, Ranch, Gun and Erlang.mk is fantastic:</p>
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" style="display:inline">
diff --git a/sitemap.xml b/sitemap.xml
index d2f546e4..bb973dd9 100644
--- a/sitemap.xml
+++ b/sitemap.xml
@@ -1224,7 +1224,12 @@
<url>
<loc>https://ninenines.eu/articles/</loc>
- <lastmod>2021-09-09T07:00:00+01:00</lastmod>
+ <lastmod>2023-01-24T07:00:00+01:00</lastmod>
+ </url>
+
+ <url>
+ <loc>https://ninenines.eu/articles/gun-2.0.0/</loc>
+ <lastmod>2023-01-24T07:00:00+01:00</lastmod>
</url>
<url>