WebSocket Test Server

This commit is contained in:
Ben Pate 2021-11-15 10:15:06 -07:00
parent 87e332ad1a
commit 6f9c3c2e03
7 changed files with 259 additions and 43 deletions

View File

@ -1,10 +1,10 @@
# WebSocket - Test Server
This package implements a bare-bones WebSocket server for testing htmx. It can be used in conjunction with the manual tests in the `/test/manual` directory.
This package implements a test-suite WebSocket server for testing htmx.
## What It Does
This listens for incoming WebSocket connections coming in to ws://localhost:1323/echo. When it receives messages from any WebSocket client, it responds with that same content in a way that htmx can process. This means, that the response message will look like this: `<div id="idMessage" hx-swap-oob="true">{your message here}</div>`
This server listens for incoming WebSocket connections coming in to ws://localhost:1323/echo. When it receives messages from any WebSocket client, it responds with that same content in a way that htmx can process. This means, that the response message will look like this: `<div id="idMessage" hx-swap-oob="true">{your message here}</div>`
## How to Use This Server

View File

@ -1,35 +1,45 @@
package main
import (
"math/rand"
"strconv"
"time"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"golang.org/x/net/websocket"
)
func wsHeartbeat(c echo.Context) error {
handler := websocket.Handler(func(ws *websocket.Conn) {
defer ws.Close()
for i := 0; ; i = i + 1 {
time.Sleep(1 * time.Second)
random := rand.Int()
message := `<div id="idMessage" hx-swap-oob="true">Message ` + strconv.Itoa(i) + `: ` + strconv.Itoa(random) + `</div>`
if err := websocket.Message.Send(ws, message); err != nil {
c.Logger().Error("send", err)
return
}
}
})
handler.ServeHTTP(c.Response(), c.Request())
return nil
}
func wsEcho(c echo.Context) error {
handler := websocket.Handler(func(ws *websocket.Conn) {
defer ws.Close()
/*
var done chan<- bool
defer func() {
close(done)
ws.Close()
}()
go func() {
for i := 0; ; i = i + 1 {
time.Sleep(10 * time.Second)
if done == nil {
return
}
websocket.Message.Send(ws, "ping #"+strconv.Itoa(i))
}
}()
*/
for {
msg := ""
@ -57,9 +67,10 @@ func main() {
e.Use(middleware.Logger())
e.Use(middleware.Recover())
e.Static("/", "../static")
e.Static("/", "./static")
e.Static("/htmx", "../../../src")
e.GET("/echo", wsEcho)
e.Logger.Fatal(e.Start(":1323"))
e.GET("/heartbeat", wsHeartbeat)
e.Logger.Fatal(e.Start(":80"))
}

View File

@ -0,0 +1,64 @@
<html>
<head>
<link rel="stylesheet" href="/stylesheet.css">
<title>&lt;/&gt; htmx WebSocket Server</title>
<script src="/htmx/htmx.js"></script>
<script src="/htmx/ext/ws.js"></script>
<script src="https://unpkg.com/hyperscript.org@0.8.3"></script>
<script type="text/hyperscript">
on click(target) from <#navigation a/>
log "got it"
take .selected for target
</script>
</head>
<body>
<div id="header"></div>
<div id="navigation" hx-target="#page" hx-push-url="false">
<a href="index.html" class="selected" hx-boost="false">About</a>
<a href="" hx-get="ws-heartbeat.html">Heartbeat Test</a>
<a href="" hx-get="ws-echo.html">Echo Test</a>
</div>
<div id="page">
<h1>WebSockets Extension Tests</h1>
<p>As of version 1.7, WebSocket support has been moved out of the core htmx library and into an extension. This server runs a test suite for the htmx WebSocket extension.</p>
<p>This extension connects to a WebSocket echo server and can send and receive messages to and from the server.</p>
<h3>Required Attributes</h3>
<table>
<tr>
<td class="bold nowrap">hx-ext</td>
<td>Make sure the SSE extension is initialized on every page or page fragment where you use SSE streams.</td>
</tr>
<tr>
<td class="bold nowrap">ws-connect</td>
<td>Connects to a WebSocket server. Attribute value must begin with ws:// wss://</td>
</tr>
<tr>
<td class="bold nowrap">ws-send</td>
<td>Add to a form to submit form data to the websocket server instead of to an HTTP server.</td>
</tr>
</table>
<h3>Example Code</h3>
<pre class="code">
&lt;body hx-ext="ws"&gt;
&lt;div ws-connect="wss://my.websocket.server.com"&gt;&lt;/div&gt;
&lt;form ws-send&gt;
&lt;input name="WebSocketMessage"&gt;
&lt;form/&gt;
&lt;/body&gt;
</pre>
<h3>WebSocket Resources</h3>
<ul>
<li><a href="https://en.wikipedia.org/wiki/WebSocket">Wikipedia</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API">MDN Web Docs</a></li>
<li><a href="https://caniuse.com/eventsource">Can I Use?</a></li>
</ul>
</div>
</body>
</html>

View File

@ -0,0 +1,112 @@
*{
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
box-sizing: border-box;
}
body {
background-color: white;
padding:0px;
margin:0px;
width:100%;
}
#header {
width:100%;
height: 100px;
background-image:url('white_transparent.svg');
background-position:left 50px center;
background-repeat:no-repeat;
background-size: 300px;
background-color:black;
}
#navigation {
position:absolute;
width:150px;
margin-top:50px;
margin-left:20px;
white-space: nowrap;
}
#navigation > a {
display:block;
cursor: pointer;
text-decoration:none;
padding:10px 20px;
}
#navigation > a:hover {
background-color:#eee;
}
#navigation > a.selected {
font-weight:bold;
}
#page {
margin: 50px;
padding-left:150px;
}
.container {
padding: 10px;
border: solid 1px gray;
margin-bottom: 20px;
background-color:#f7f7f7;
}
.container.htmx-settling {
border:solid 3px red!important;
padding:8px!important;
}
pre.code {
font-family:'Courier New', Courier, monospace;
background-color: #444440;
color: #0f0;
padding:30px 5px 30px 15px;
overflow-y:scroll;
display:block;
}
.bold {
font-weight:bold;
}
.nowrap {
white-space: nowrap;
}
table {
border-collapse: collapse;
}
td {
padding:10px 20px;
border:solid 1px #ddd;
vertical-align: top;
}
.demo {
padding:10px;
margin:20px 0px;
color:white;
background-color: #999;
height:100px;
}
a, a:visited {
color:#3465a4;
}
.btn {
padding:5px 10px;
border:none;
border-radius:5px;
}
.btn.primary {
background-color:#3465a4;
color:white;
}

View File

@ -1,21 +0,0 @@
<html>
<head>
<script src="../../src/htmx.js"></script>
<script src="../../src/ext/ws.js"></script>
<title>WebSockets Test</title>
</head>
<body hx-ext="ws" ws-connect="ws://localhost:1323/echo">
<form ws-send="">
<div>Send Message to Echo Server...</div>
<div>
<input type="text" name="message" style="width:500px;" value="This Is The Message" />
<input type="submit"/>
</div>
</form>
<br><hr><br>
<div id="idMessage"></div>
</body>
</html>

View File

@ -0,0 +1,33 @@
<h1>Echo Test</h1>
<h3>Description</h3>
<p>This test lets you send and receive data to and from the WebSocket server. Every message that you send to the server will be "echoed"
back to you in a separate message</p>
<h3>Example HTML</h3>
<pre class="code">
&lt;div hx-ext="ws" ws-connect="ws://localhost/echo"&gt;
&lt;form ws-send&gt;
&lt;input type="text" name="message" style="width:500px;" value="This Is The Message" /&gt;
&lt;input type="submit"/&gt;
&lt;/form&gt;
&lt;div id="idMessage"&gt;&lt;/div&gt;
&lt;/div&gt;
</pre>
<div class="container" hx-ext="ws" ws-connect="ws://localhost/echo">
<form ws-send="">
<h3>Send a Message</h3>
<div>
<input type="text" name="message" style="width:500px;" value="This Is The Message" />
<input type="submit" value="Send" class="btn primary"/>
</div>
</form>
<br>
<h3>Receive a Message</h3>
<div id="idMessage"></div>
</div>

View File

@ -0,0 +1,17 @@
<h1>Heartbeat Test</h1>
<h3>Description</h3>
<p>This test receives messages from the WebSocket server every second.
<h3>Example HTML</h3>
<pre class="code">
&lt;div hx-ext="ws" ws-connect="ws://localhost/heartbeat"&gt;
&lt;div id="idMessage"&gt;&lt;/div&gt;
&lt;/div&gt;
</pre>
<div class="container" hx-ext="ws" ws-connect="ws://localhost/heartbeat">
<h3>WebSocket Messages</h3>
<p>Each message just contains a random number generated by the server</p>
<div id="idMessage">Waiting...</div>
</div>