Skip to content

Instantly share code, notes, and snippets.

@iffy

iffy/Dockerfile Secret

Created January 22, 2023 04:58
Show Gist options
  • Save iffy/f2a4bcd78af9d8ae8e71f583b310e410 to your computer and use it in GitHub Desktop.
Save iffy/f2a4bcd78af9d8ae8e71f583b310e410 to your computer and use it in GitHub Desktop.
Demonstration of nim-websock not working on a fly.io hosted app
FROM nimlang/nim:1.6.10-alpine@sha256:408ebac99ad2d170a59e7a09c10e82e7336cf71fa38c7a1322aaa598a54d32c2 as builder
WORKDIR /app
RUN apk update && apk add musl-dev
RUN nimble install -y chronos websock
COPY . .
RUN nim c --gc:orc -o:testapp main.nim
RUN ls -al
WORKDIR /root/
RUN cp /app/testapp /usr/local/bin/
CMD ["/usr/local/bin/testapp"]
import std/uri
import pkg/chronos
import pkg/chronicles
import pkg/httputils
import websock/[websock, extensions/compression/deflate]
proc handle(request: HttpRequest) {.async.} =
echo "Handling request:", request.uri.path
if request.uri.path == "/ws":
try:
let deflateFactory = deflateFactory()
let server = WSServer.new(factories = [deflateFactory])
let ws = await server.handleRequest(request)
if ws.readyState != Open:
error "Failed to open websocket connection"
return
echo "Websocket handshake completed"
while ws.readyState != ReadyState.Closed:
let recvData = await ws.recvMsg()
echo "Client Response: ", $recvData.len
if ws.readyState == ReadyState.Closed:
# if session already terminated by peer,
# no need to send response
break
await ws.send(recvData,
if ws.binary: Opcode.Binary else: Opcode.Text)
except WebSocketError as exc:
error "WebSocket error:", exception = exc.msg
else:
await request.sendResponse(Http200, data = "Hello, world!")
when isMainModule:
proc main() {.async.} =
let
socketFlags = {ServerFlags.TcpNoDelay, ServerFlags.ReuseAddr}
server = HttpServer.create(initTAddress("0.0.0.0:8080"), flags = socketFlags)
server.handler = handle
server.start()
echo "Server listening on ", $server.localAddress()
await server.join()
waitFor(main())
## Try connecting to various servers to see if they work
import std/strformat
import std/uri
import chronos
import chronos/apps/http/httpclient
import chronicles
import websock/websock
## CHANGE THIS if you deploy something on fly.io
const flyAppHostname = "quiet-shape-2200.fly.dev"
template maybe(x: untyped): untyped =
try: x
except: echo "FAILED: ", getCurrentExceptionMsg()
proc string(x: seq[byte]): string =
for c in x:
result.add(chr(c))
proc httpGet(uri: string) {.async.} =
echo "\nhttpGet ", uri
let session = HttpSessionRef.new()
let resp = await session.fetch(uri.parseUri)
echo " status: ", $resp.status
echo " resp: ", resp.data.string
proc sendAndReceive(uri: string) {.async.} =
echo "\nsendAndReceive ", uri
let ws = await WebSocket.connect(
parseUri(uri),
flags = {TLSFlags.NoVerifyHost, TLSFlags.NoVerifyServerName},
# hostName = hostname,
)
echo " sending ..."
await ws.send("hello, world!")
echo " sent"
let resp = await ws.recvMsg()
echo " got response: ", resp.string
proc main {.async.} =
# an echo websockets server
maybe await sendAndReceive("wss://ws.postman-echo.com/raw")
# Not a websockets server
maybe await wait(sendAndReceive("wss://www.google.com/"), 3.seconds)
# HTTP
maybe await httpGet(&"https://{flyAppHostname}/")
maybe await wait(sendAndReceive(&"wss://{flyAppHostname}/ws"), 3.seconds)
waitFor main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment