Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to broadcast a WS response from a HTTPS endpoint?🤔 #57

Closed
marcelo-tm opened this issue Sep 27, 2020 · 12 comments
Closed
Labels
🤔 Question Further information is requested

Comments

@marcelo-tm
Copy link

Hello everyone, I'm starting with websockets and I would like to know if it is possible to send a WS notification after some action is done inside a HTTPS endpoint. For example, I want to notify some users (I still need to figure out how to broadcast just to some users) when a new User is created on the admin panel. A POST request is made to the endpoint /agent and I would like to use websockets to send this new data and populate a data grid when a certain user is on the Agents creation screen.

I don't know if its clear, but is it possible to be made?

Thanks in advance.

@marcelo-tm marcelo-tm added the 🤔 Question Further information is requested label Sep 27, 2020
@welcome
Copy link

welcome bot commented Sep 27, 2020

Thanks for opening your first issue here! 🎉 Be sure to follow the issue template!

@WLun001
Copy link
Contributor

WLun001 commented Oct 5, 2020

Hi @maverickVision, I think you need separate websocket for that. And your API server connects to your websocket

app.Get("/operation", func (c *fiber.Ctx) error {

ws.send('message')

return c.SendString("done!")
})

@marcelo-tm
Copy link
Author

Hi @WLun001, I've created this simple repo with the minimal working structure using fiber and it's websockets plugin, could you help me modify it to get it working?

https://github.com/maverickVision/testws

@WLun001
Copy link
Contributor

WLun001 commented Oct 5, 2020

@maverickVision I am not free at the moment, maybe you could take a look at this repo that address the same issue.

Checkout on problem branch.

@marcelo-tm
Copy link
Author

Thanks @WLun001, I'll take a look. But I already saw that you are using the gin framework. Since I'm still beggining with Go, do you think it's better to learn gin instead of fiber?

@Fenny
Copy link
Member

Fenny commented Oct 5, 2020

I'm not sure if I fully understand the question, but are you trying to run a websocket server with TLS?

package main

import (
	"crypto/tls"
	"log"

	"github.com/gofiber/fiber/v2"
	"github.com/gofiber/websocket/v2"
)

func main() {
	// Fiber instance
	app := fiber.New()

	// Websocket upgrade
	app.Get("/ws", websocket.New(func(c *websocket.Conn) {
		var (
			mt  int
			msg []byte
			err error
		)
		for {
			if mt, msg, err = c.ReadMessage(); err != nil {
				log.Println("read:", err)
				break
			}
			log.Printf("recv: %s", msg)

			if err = c.WriteMessage(mt, msg); err != nil {
				log.Println("write:", err)
				break
			}
		}
	}))

	// Load tls certificate
	cer, err := tls.LoadX509KeyPair("./certs/ssl.cert", "./certs/ssl.key")
	if err != nil {
		log.Fatal(err)
	}

	config := &tls.Config{Certificates: []tls.Certificate{cer}}

	// Create custom listener
	ln, err := tls.Listen("tcp", ":443", config)
	if err != nil {
		panic(err)
	}

	// Access the websocket server: wss://localhost:443/ws
	// https://www.websocket.org/echo.html
	log.Fatal(app.Listener(ln))
}

@WLun001
Copy link
Contributor

WLun001 commented Oct 6, 2020

Thanks @WLun001, I'll take a look. But I already saw that you are using the gin framework. Since I'm still beggining with Go, do you think it's better to learn gin instead of fiber?

@maverickVision If you coming from Express, Fiber would be good choice, it has familiar APIs. Any framework will do, or without framework. That's my personal opinion.

@marcelo-tm
Copy link
Author

@maverickVision I am not free at the moment, maybe you could take a look at this repo that address the same issue.

Checkout on problem branch.

@WLun001 I'm following your code from this repo, on the solution brach. The problem with fiber is that I can't access the responseWriter from fiber Context, in order to upgrade the connection inside the ServeWs method... and according to this issue #721, it is really not possible. I guess I will need to rewrite my project with Gin just because of this issue.

@WLun001
Copy link
Contributor

WLun001 commented Oct 12, 2020

@maverickVision You don't need to access to responseWriter. You could use https://github.com/gofiber/websocket.

@marcelo-tm
Copy link
Author

@maverickVision You don't need to access to responseWriter. You could use https://github.com/gofiber/websocket.

I've made the following changes:

main.go

app.Get("/ws", websocket.New(func(c *websocket.Conn) {
		ws.ServeWs(hub, c, nc, subject)
	}))

ws.go

func ServeWs(hub *Hub, conn *websocket.Conn, nc *nats.Conn, subject string) {
	client := &Client{hub: hub, conn: conn, send: make(chan []byte, 256)}

	// subscribe nats
	sub, err := nc.Subscribe(subject, func(m *nats.Msg) {
		log.Println(string(m.Data))
		client.hub.broadcast <- m.Data
	})
	if err != nil {
		log.Fatal(err)
	}
	nc.Flush()

	if err := nc.LastError(); err != nil {
		log.Fatal(err)
	}

	client.natsSub = sub
	client.hub.register <- client

	// Allow Connection of memory referenced by the calloer by doing all work in new goroutines
	go client.writePump()
	go client.readPump()
}

I've switched the conn variable from the upgraded gin context to fiber websocket conn. All services gone up without issues (using the same commands you use in your code), but when I open a browser tab on localhost:8080, I get the following error on the make start-api console log:

2020/10/12 13:53:44 ws.go:64: Current connected ws client: 1
2020/10/12 13:53:44 ws.go:71: Unsubscribe
2020/10/12 13:53:44 ws.go:74: Current connected ws client: 0
panic: runtime error: invalid memory address or nil pointer dereference
	panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x149e03e]

goroutine 8 [running]:
github.com/fasthttp/websocket.(*Conn).Close(...)
	/Users/marcelo/go/pkg/mod/github.com/fasthttp/websocket@v1.4.3-beta.2/conn.go:344
github.com/maverickvision/testws/internal/ws.(*Client).writePump.func1(0xc00007e320, 0xc00028a0a0)
	/Users/marcelo/playground/golang/testws/internal/ws/ws.go:160 +0x3e
panic(0x150bc00, 0x1a06520)
	/usr/local/go/src/runtime/panic.go:969 +0x166
github.com/fasthttp/websocket.(*Conn).SetWriteDeadline(...)
	/Users/marcelo/go/pkg/mod/github.com/fasthttp/websocket@v1.4.3-beta.2/conn.go:781
github.com/maverickvision/testws/internal/ws.(*Client).writePump(0xc00028a0a0)
	/Users/marcelo/playground/golang/testws/internal/ws/ws.go:166 +0x311
created by github.com/maverickvision/testws/internal/ws.ServeWs
	/Users/marcelo/playground/golang/testws/internal/ws/ws.go:221 +0x240

I printed the conn and client variables on ws.go, and they are not null, what could it be?

I've updated my repo with the latest code, if you can help.

@WLun001
Copy link
Contributor

WLun001 commented Oct 14, 2020

@maverickVision I created a simplified example,using websocket in Fiber. You may take a look at this repo

@Fenny
Copy link
Member

Fenny commented Oct 22, 2020

Closing due to inactivity, feel free to re-open.

@Fenny Fenny closed this as completed Oct 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🤔 Question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants