mirror of
https://github.com/bigskysoftware/htmx.git
synced 2025-09-28 21:41:40 +00:00
WebSocket Test Server
This commit is contained in:
parent
87e332ad1a
commit
6f9c3c2e03
@ -1,10 +1,10 @@
|
|||||||
# WebSocket - Test Server
|
# 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
|
## 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
|
## How to Use This Server
|
||||||
|
|
||||||
|
@ -1,35 +1,45 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/labstack/echo/v4/middleware"
|
"github.com/labstack/echo/v4/middleware"
|
||||||
"golang.org/x/net/websocket"
|
"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 {
|
func wsEcho(c echo.Context) error {
|
||||||
|
|
||||||
handler := websocket.Handler(func(ws *websocket.Conn) {
|
handler := websocket.Handler(func(ws *websocket.Conn) {
|
||||||
|
|
||||||
defer ws.Close()
|
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 {
|
for {
|
||||||
|
|
||||||
msg := ""
|
msg := ""
|
||||||
@ -57,9 +67,10 @@ func main() {
|
|||||||
e.Use(middleware.Logger())
|
e.Use(middleware.Logger())
|
||||||
e.Use(middleware.Recover())
|
e.Use(middleware.Recover())
|
||||||
|
|
||||||
e.Static("/", "../static")
|
e.Static("/", "./static")
|
||||||
e.Static("/htmx", "../../../src")
|
e.Static("/htmx", "../../../src")
|
||||||
|
|
||||||
e.GET("/echo", wsEcho)
|
e.GET("/echo", wsEcho)
|
||||||
e.Logger.Fatal(e.Start(":1323"))
|
e.GET("/heartbeat", wsHeartbeat)
|
||||||
|
e.Logger.Fatal(e.Start(":80"))
|
||||||
}
|
}
|
||||||
|
64
test/servers/ws/static/index.html
Normal file
64
test/servers/ws/static/index.html
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="/stylesheet.css">
|
||||||
|
<title></> 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">
|
||||||
|
<body hx-ext="ws">
|
||||||
|
<div ws-connect="wss://my.websocket.server.com"></div>
|
||||||
|
|
||||||
|
<form ws-send>
|
||||||
|
<input name="WebSocketMessage">
|
||||||
|
<form/>
|
||||||
|
</body>
|
||||||
|
</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>
|
112
test/servers/ws/static/stylesheet.css
Normal file
112
test/servers/ws/static/stylesheet.css
Normal 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;
|
||||||
|
}
|
@ -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>
|
|
33
test/servers/ws/static/ws-echo.html
Normal file
33
test/servers/ws/static/ws-echo.html
Normal 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">
|
||||||
|
<div hx-ext="ws" ws-connect="ws://localhost/echo">
|
||||||
|
|
||||||
|
<form ws-send>
|
||||||
|
<input type="text" name="message" style="width:500px;" value="This Is The Message" />
|
||||||
|
<input type="submit"/>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div id="idMessage"></div>
|
||||||
|
</div>
|
||||||
|
</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>
|
17
test/servers/ws/static/ws-heartbeat.html
Normal file
17
test/servers/ws/static/ws-heartbeat.html
Normal 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">
|
||||||
|
<div hx-ext="ws" ws-connect="ws://localhost/heartbeat">
|
||||||
|
<div id="idMessage"></div>
|
||||||
|
</div>
|
||||||
|
</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>
|
Loading…
x
Reference in New Issue
Block a user