<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="173251" data-post-id="173251">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="HappyBee" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/HappyBee/120/39467_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  HappyBee
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>well, I agree… I’ve no intension of offending anyone. If you get that vibe, I apologize. Thanks for the link though.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="173251" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/suppressing-muting-the-server-response-header-in-phoenix/29438/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-173251" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="173251"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #11"></div>
  </section>
</div>
    <div class="postbit" id="173256" data-post-id="173256">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="HappyBee" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/HappyBee/120/39467_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  HappyBee
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Blog post you had linked, solved the issues with normal http requests, but when there is a websocket upgrade request I still see the <code>server</code> header, how can we remove header even when there is a connection upgrade?</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">HTTP/1.1 101 Switching Protocols
cache-control: max-age=0, private, must-revalidate
connection: Upgrade
date: XXXX XXX
sec-websocket-accept: VmcZDLx2TP5aKLFproPFiyryze4=
server: Cowboy
upgrade: websocket
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="173256" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/suppressing-muting-the-server-response-header-in-phoenix/29438/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-173256" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="173256"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #12"></div>
  </section>
</div>
    <div class="postbit" id="177403" data-post-id="177403">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="dunson062786" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  dunson062786
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I too am experiencing this issue when there is a websocket upgrade request.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="177403" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/suppressing-muting-the-server-response-header-in-phoenix/29438/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-177403" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="177403"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #13"></div>
  </section>
</div>
    <div class="postbit" id="277927" data-post-id="277927">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="mithereal" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mithereal/120/4455_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  mithereal
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>there was a couple of pattern matches missing here is an updated plug</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule MyApp.Plugs.StripHeaderHandler do
  @behaviour :cowboy_stream

  def info(stream_id, {:response, status, headers, body}, state) do
    headers = Map.drop(headers, ["server"])
    :cowboy_stream.info(stream_id, {:response, status, headers, body}, state)
  end

  def info(stream_id, {:inform, status, headers, body}, state) do
    headers = Map.drop(headers, ["server"])
    :cowboy_stream.info(stream_id, {:response, status, headers, body}, state)
  end

  def info(stream_id, {:switch_protocol, status, headers, body}, state) do
    headers = Map.drop(headers, ["server"])
    :cowboy_stream.info(stream_id, {:response, status, headers, body}, state)
  end

  def info(stream_id, info, state), do: :cowboy_stream.info(stream_id, info, state)
  end

  def init(stream_id, req, opts), do: :cowboy_stream.init(stream_id, req, opts)

  def data(stream_id, is_fin, info, state),
      do: :cowboy_stream.data(stream_id, is_fin, info, state)

  def early_error(stream_id, reason, partial_req, resp, opts),
      do: :cowboy_stream.early_error(stream_id, reason, partial_req, resp, opts)

  def terminate(stream_id, reason, state), do: :cowboy_stream.terminate(stream_id, reason, state)
end
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="277927" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/suppressing-muting-the-server-response-header-in-phoenix/29438/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-277927" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="277927"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #14"></div>
  </section>
</div>
    <div class="postbit" id="277929" data-post-id="277929">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="D4no0" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/D4no0/120/33624_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  D4no0
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Actually this is a very valid point, why do most servers echo the technology behind them? I wonder if there is any real usage to this beside getting sniffed and fingerprinted…</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="277929" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/suppressing-muting-the-server-response-header-in-phoenix/29438/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-277929" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="277929"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #15"></div>
  </section>
</div>
    <div class="postbit" id="280569" data-post-id="280569">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="mithereal" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mithereal/120/4455_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  mithereal
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>you need to add stream handlers under prod http</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">config :web, Web.Endpoint,
  url: [host: "example.com", port: 80],
  http: [stream_handlers: [:cowboy_compress_h, Web.Plugs.StripHeaderHandler, :cowboy_stream_h]],
  check_origin: false,
  orce_ssl: [rewrite_on: [:x_forwarded_proto]],
  cache_static_manifest: "priv/static/cache_manifest.json",
  socket_options: [:inet6],
  force_ssl: [
    host: nil,
    rewrite_on: [:x_forwarded_port, :x_forwarded_proto],
    # maybe true when we use this for real
    hsts: false
  ]

</code></pre>
<p>module</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">
defmodule Web.Plugs.StripHeaderHandler do
  @behaviour :cowboy_stream
  @server_name "my server name"
  @websocket_name :websocket

  def info(stream_id, {:response, status, headers, body}, state) do
    #    headers = Map.drop(headers, ["server"])
    headers = Map.put(headers, "server", @server_name)
    :cowboy_stream.info(stream_id, {:response, status, headers, body}, state)
  end

  def info(stream_id, {:inform, status, headers, _body}, state) do
    status = Map.put(headers, "server", @server_name)
    headers = @websocket_name 
    :cowboy_stream.info(stream_id, {:inform, status, headers}, state)
  end

  def info(stream_id, {:switch_protocol, status, headers, _body}, state) do

    status = Map.put(status, "server", @server_name)
    headers = @websocket_name
    :cowboy_stream.info(stream_id, {:switch_protocol, status, headers}, state)
  end

  def info(stream_id, info, state), do: :cowboy_stream.info(stream_id, info, state)

  def init(stream_id, req, opts), do: :cowboy_stream.init(stream_id, req, opts)

  def data(stream_id, is_fin, info, state),
    do: :cowboy_stream.data(stream_id, is_fin, info, state)

  def early_error(stream_id, reason, partial_req, resp, opts),
    do: :cowboy_stream.early_error(stream_id, reason, partial_req, resp, opts)

  def terminate(stream_id, reason, state), do: :cowboy_stream.terminate(stream_id, reason, state)
end

</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="280569" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/suppressing-muting-the-server-response-header-in-phoenix/29438/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-280569" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="280569"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #16"></div>
  </section>
</div>
    <div class="postbit" id="332325" data-post-id="332325">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="s6o" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  s6o
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>My updated version, removing the <code>server</code> header without breaking websocket initialisation. In the <code>:switch_protocol</code> headers are in the 2nd element of the tuple. Tested with cowboy 2.12, plug_cowboy 2.7.1, phoenix 1.7.14, phoenix_live_dashboard 0.8.4.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule MyApiWeb.Plugs.StripServerHeader do
  @moduledoc """
  Strip the Cowboy's `server` header from HTTP responses to minimise fingerprinting.
  """
  @behaviour :cowboy_stream

  def info(stream_id, {:response, status, headers, body}, state) do
    headers = Map.drop(headers, ["server"])
    :cowboy_stream.info(stream_id, {:response, status, headers, body}, state)
  end

  def info(stream_id, {:inform, status, headers}, state) do
    headers = Map.drop(headers, ["server"])
    :cowboy_stream.info(stream_id, {:inform, status, headers}, state)
  end

  def info(stream_id, {:switch_protocol, headers, status, body}, state) do
    headers = Map.drop(headers, ["server"])
    :cowboy_stream.info(stream_id, {:switch_protocol, headers, status, body}, state)
  end

  def info(stream_id, info, state) do
    #    IO.inspect(info, label: "strip-header-info")
    :cowboy_stream.info(stream_id, info, state)
  end

  def init(stream_id, req, opts), do: :cowboy_stream.init(stream_id, req, opts)

  def data(stream_id, is_fin, info, state),
    do: :cowboy_stream.data(stream_id, is_fin, info, state)

  def early_error(stream_id, reason, partial_req, resp, opts),
    do: :cowboy_stream.early_error(stream_id, reason, partial_req, resp, opts)

  def terminate(stream_id, reason, state), do: :cowboy_stream.terminate(stream_id, reason, state)
end
</code></pre>
<p>The endpoint configuration example:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  config :ov_api, MyApiWeb.Endpoint,
    url: [host: host],
    http: [
      ip: {127, 0, 0, 1},
      port: port,
      stream_handlers: [:cowboy_compress_h, MyApiWeb.Plugs.StripServerHeader, :cowboy_stream_h]
    ],
# ...
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="332325" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/suppressing-muting-the-server-response-header-in-phoenix/29438/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-332325" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="332325"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-last-post cat-last-post" title="Last post!"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <span class="all-loaded">— All posts loaded —</span>
</div></template></turbo-stream>