title: How to properly refuse websocket upgrade request?
body: <p>Sometimes I want to refuse a http client's request to upgrade connection to websocket.</p>
  <hr />
  <h2>Code</h2>
  <p><em>(using <code>go</code>'s <code>Gin</code> and <code>gorilla/websocket</code> framework:)</em></p>
  <p>To <strong>allow</strong> upgrade:</p>
  <pre><code>c, err := ctl.upgrader.Upgrade(ctx.Writer, ctx.Request, nil)
  err = c.WriteJSON(resp)
  </code></pre>
  <p>To <strong>refuse</strong> upgrade <em>(due to invalid request params)</em>:</p>
  <pre><code>if contentId == &quot;&quot; || !exists {
      // FIXME: provide response in a way that ws client can recognize &amp; show tip?
      ctx.String(http.StatusBadRequest, &quot;invalid or non-existing contentId&quot;)
      return
  }
  </code></pre>
  <p><strong>Explaination</strong>: Here to refuse the upgrade I just return a http <code>400</code> code, then terminate the connection, and didn't do the upgrade at all.</p>
  <hr />
  <h2>The issue</h2>
  <p>The problem to refuse websocket upgrade request with about code is that, the websocket client <em>(e.g <code>js</code>)</em>, can't read data <em>(text or json)</em> in my response.</p>
  <p><strong>Code - client-side <em>(<code>js</code>)</em>:</strong></p>
  <pre><code>ws.onerror = function (evt) {
      // TOOD: handle error, (e.g print error msg?),
      print(&quot;ERROR&quot;);
  }
  </code></pre>
  <p>It does print the <code>&quot;ERROR&quot;</code> on refuse, but after checking chrome developer tool about the <code>evt</code> object, can't find a way to get server response data, so I can't show tip to frontend UI with reason of refuse.</p>
  <hr />
  <h2>Questions</h2>
  <ul>
  <li>How to refuse websocket upgrade request properly, and let client be able to receive the returned reason/data ? (e.g <strong>client</strong> is <code>js</code>, <strong>server</strong> is <code>go</code> / <code>gin</code> / <code>gorilla/websocket</code>).</li>
  <li>Is there a better way to refuse websocket upgrade request, other than return http code like <code>400</code>?</li>
  </ul>