julienschmidt / httprouter

A high performance HTTP request router that scales well
https://pkg.go.dev/github.com/julienschmidt/httprouter
BSD 3-Clause "New" or "Revised" License
16.62k stars 1.47k forks source link

How can i implement a websocket using httprouter #309

Open dbhys4github opened 4 years ago

dbhys4github commented 4 years ago

As the title:How can i implement a websocket using httprouter?

han-so1omon commented 4 years ago

I got it working with something like the code below. I'm using gorilla/websocket for websocket connection management and messaging.

//////////////////////////// server.go
package main

import (
    "github.com/gorilla/websocket"
    "github.com/julienschmidt/httprouter"
    "log"
    "net/http"
)

var upgrader = websocket.Upgrader{}

func internalError(ws *websocket.Conn, msg string, err error) {
    log.Println(msg, err)
    ws.WriteMessage(websocket.TextMessage, []byte("Internal server error."))
}

func sendStuff(ws *websocket.Conn, /* stuff */) {
    ws.WriteMessage(websocket.TextMessage, []byte(/* stuff */)
}

func Connect(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
    // Setup websocket
    ws, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Println("upgrade:", err)
        return
    }

        // Do some preprocessing here...

    defer ws.Close()

    // Do some more processing if you want...
    done := false
    for {
        select {
        case /* <-appDone */:
            done = true
        case /* <-appUpdated */:
            go sendStuff(ws, /*stuff*/)
        }
        if done {
            break
        }
    }
}
func NewRouter() *httprouter.Router {
    router := httprouter.New()
    router.GET("/ws", Connect)

    return router
}

//////////////////////////// main.go
package main

import (
    "log"
    "net/http"
)

func main() {
    log.Println("Starting app")
    // Get new router
    router := NewRouter()
    // Serve routes
    http.ListenAndServe(":8900", router)
}

Here's my client skeleton code as well in Python.

import os
import sys
import websocket

try:
    import thread
except ImportError:
    import _thread as thread

import time

def process_message(message):
    print(message)

def on_message(ws, message):
    process_message(message)

def on_error(ws, error):
    print("error")
    print(error)

def on_close(ws):
    print("### end ###")

def on_open(ws):
    def run(*args):
        while True:
            time.sleep(1)
        time.sleep(1)
        ws.close()
        print("terminating websocket...")
    thread.start_new_thread(run, ())

if __name__ == "__main__":
    websocket.enableTrace(True)
    ws = websocket.WebSocketApp(
            "ws://localhost:8900/ws",
            on_message = on_message,
            on_error = on_error,
            on_close = on_close)
    ws.on_open = on_open
    ws.run_forever()

This confused me a bit as well, as I wasn't sure which http method to use with a websocket. I settled on the GET method, as that's what I've seen in some other places. Everything else as shown, substituting POST instead of GET yields 405 Method Not Allowed.

han-so1omon commented 4 years ago

@julienschmidt I recommend closing this issue and labeling as question