Run web-Socket locally for debug - go

I’m using gorilla web socket and I want to run it locally , I mean with the following chrome client
or other recommended tool …when I run into debug mode I got error
I use
"github.com/gorilla/websocket"
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}
upgrader.CheckOrigin = func(r *http.Request) bool { return true }
c, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Print("upgrade:", err)
return
}
When I run the following url in chrome or web socket client I got error
websocket: not a websocket handshake: 'upgrade' token not found in 'Connection' header
localhost:8081/mypath
and I want to run it
ws://localhost:8081/mypath
and provide token for local simulation, how I can do it ?
To check it I use Simple WebSocket Client of chrome. any other client will be helpful
EDIT:
when I try it in the chrome console I got the following error:
VM42:164 Refused to connect to 'ws://localhost:8081/mypath' because it
violates the following Content Security Policy directive: "connect-src
'self' uploads.github.com status.github.com collector.githubapp.com
api.github.com www.google-analytics.com github-cloud.s3.amazonaws.com
github-production-repository-file-5c1aeb.s3.amazonaws.com
github-production-upload-manifest-file-7fdce7.s3.amazonaws.com
github-production-user-asset-6210df.s3.amazonaws.com
wss://live.github.com

Browsers do not use the WebSocket protocol when fetching a web page for display. Code is required to use a WebSocket endpoint from a browser.
The Gorilla package includes examples showing how to connect from a browser (the chat and command examples are good places to start).
You can can connect to a WebSocket endpoint using the browser console:
> ws = new WebSocket("ws://localhost:8080/mypath")
> ws.onmessage = function(ev) { console.log(ev.data) }
> ws.send("hello")

Related

OAuth Authorization in Golang CLI Applications

I've been using the code from the OAuth2 package documentation to add authorization to my CLI application, but I've run into a bit of a snag.
package main
import (
"context"
"fmt"
"log"
"golang.org/x/oauth2"
)
func main() {
ctx := context.Background()
conf := &oauth2.Config{
ClientID: "YOUR_CLIENT_ID",
ClientSecret: "YOUR_CLIENT_SECRET",
Scopes: []string{"SCOPE1", "SCOPE2"},
Endpoint: oauth2.Endpoint{
AuthURL: "https://provider.com/o/oauth2/auth",
TokenURL: "https://provider.com/o/oauth2/token",
},
}
// Redirect user to consent page to ask for permission
// for the scopes specified above.
url := conf.AuthCodeURL("state", oauth2.AccessTypeOffline)
fmt.Printf("Visit the URL for the auth dialog: %v", url)
// Use the authorization code that is pushed to the redirect
// URL. Exchange will do the handshake to retrieve the
// initial access token. The HTTP Client returned by
// conf.Client will refresh the token as necessary.
var code string
if _, err := fmt.Scan(&code); err != nil {
log.Fatal(err)
}
tok, err := conf.Exchange(ctx, code)
if err != nil {
log.Fatal(err)
}
client := conf.Client(ctx, tok)
client.Get("...")
}
I'm using StackOverflow as the authorization server and api.stackexchange.com doc says the following. But I'm not sure what it means.
Desktop applications cannot participate directly in OAuth 2.0 flows, however the embeddable browser controls available in most frameworks make it possible to work around this limitation.
The issue is that when I use the method described in the documentation, I have to manually click the URL generated in the CLI and manually copy the access token to continue.
Do you happen to know of a way to automate these two steps in Golang or a different approach I could take for authorization in CLI applications?
What I'm hoping for is something like what you see in the heroku-cli but with OAuth 2.0 - it would be awesome if my app could handle authorization in a similar way. Thanks for your help!
I'd really appreciate any help or advice you can offer. Thanks!

GRPC over HTTPS proper client initialization in Go

I'm interfacing from my code certain 3rd party software (particularly chirpstack v4) which provides API via GPRC. When deployed locally, it answers via HTTP and I get the response all right.
However in cluster we have the same server deployed with HTTPS (with letsencrypt certificate, not something private) so I'm trying to add corresponding transport layer security settings, but to my surprise I got then
rpc error: code = Internal desc = unexpected HTTP status code received from server: 400 (Bad Request); malformed header: missing HTTP content-type
I tried adding SetHeader to context with content-type: application/grpc but this won't change anything so I'm not sure it is really about header (moreover that it works with plain HTTP). So I wonder, perhaps anyone can point me some mistake in initialization of transport layer security?
// this is used with plain HTTP
//opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
// this for case of working via HTTPS
opts := []grpc.DialOption{grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{}))}
// also tried NewClientTLSFromCert(x509.SystemCertPool()) - the same
serverAddr := "our-public-address:443"
ctx := context.Background()
conn, err := grpc.Dial(serverAddr, opts...)
if err != nil {
println("Dial error:", err.Error())
return
}
cli := api.NewInternalServiceClient(conn)
req := &api.LoginRequest{Email: "admin", Password: "admin"}
resp, err := cli.Login(ctx, req) // error arises here
if err != nil {
println("login failed", err.Error())
}
Thanks in advance for hints and suggestions!

HTTP2 with defined proxy function that supports http requests in golang

I have a specific use case, where I have to use HTTP2 protocol with a proxy configured. This proxy function uses the request to determine, which proxy URL to use.
Since http2.transport{} struct does not have a proxy field, I was using:
httpTransport := &http.Transport{
Proxy: *ProxyFunction, // var ProxyFunction *func(*http.Request) (*url.URL, error)
ForceAttemptHTTP2: true,
}
http2.ConfigureTransport(httpTransport)
But, this does not allow me to send "http://" requests as HTTP2. Only "https://" were sent as HTTP2, "http://" requests were using HTTP1.1
This leads me to
httpTransport := &http.Transport{
Proxy: *config.ProxyFunction,
ForceAttemptHTTP2: true,
}
h2, _ := http2.ConfigureTransports(httpTransport)
h2.AllowHTTP = true
But using this config, on request, I receive
error getting: Get http://google.com: http2: no cached connection was available, similar to https://github.com/golang/go/issues/26479
Since there is no official support, what would be the right approach to achieve this?
Can I use a dialer to achieve this?
Note:
proxy URL is obtained from ProxyFunction *func(*http.Request) (*url.URL, error) and changes based on the request
https is not a requirement and need not be supported.
go version go1.13.7

Golang websocket nil memory error

Below is the code of my websocket server.
http.Handle("/gatewayconnector", websocket.Handler(socketHandler))
Method socketHandler has the code below:
func socketHandler(ws *websocket.Conn) {
LoadClient(ws)
var msg []byte
for {
if err := websocket.Message.Receive(ws, &msg); err != nil {
log.Error("Error in socketHandler: ", err)
break
}
validateMessage(msg)
}
}
The socket handler call back method get called when handshake happened from client and it also initiate the websocket object. So at very first step of this method i stored this websocket object into an array, so that i can retrieve it at the send method call (used to send message to client).
The issue is sometimes I'm getting nil memory reference in ws i.e. the websocket while trying to send some message to client.
Below is the send method code:
func Send(msg interface{}) error {
ws := webSocketClients[0]
if (ws == nil) {
log.Error("Websocket connection is nil, gateway should initiate the connection.")
}
return websocket.JSON.Send(ws, msg)
}
This issue arises when websocket connection remanis idle for a longer persiod of time and I call directly the send method.
Right now i have put one hack that client will ping my websocket server at regular interval to avoid this.
How to avoid this kind of problem?
Pinging websocket connection on interval is normal thing to do, please check how it's done in Gorilla Websocket Chat Example. I know you're using net/websocket, but the idea should be similar. The problem is that you can't rely that your long-time TCP connection will remain active, especially in public networks. Some firewalls silently RST connections without traffic flow after some period of time.

Serving a websocket in Go

I'm starting to play around with websockets + go and well I think I'm misunderstanding something quite basic with websockets in Go.
I'd like to simply listen for a websocket connection and process accordingly. However all examples I see in Go using websocket is serving the web page that then connects to the websocket, is this a requirement?
The following is a basic echo server I have setup:
package main
import (
"fmt"
"code.google.com/p/go.net/websocket"
"net/http"
)
func webHandler(ws *websocket.Conn) {
var s string
fmt.Fscan(ws, &s)
fmt.Println("Received: ", s)
}
func main() {
fmt.Println("Starting websock server: ")
http.Handle("/echo", websocket.Handler(webHandler))
err := http.ListenAndServe(":8080", nil)
if err != nil {
panic("ListenAndServe: " + err.Error())
}
}
This is the javascript used to connect:
ws = new WebSocket("ws://localhost:8080/echo");
ws.onmessage = function(e) {
console.log("websock: " + e.data);
};
However this results in:
WebSocket connection to 'ws://localhost:8080/echo' failed: Unexpected response code: 403
When working with websockets from Javascript, you will seldom have to read the frames directly. To be honest, I am not even sure how to do that.
Fortunately, the websocket package already has a type, Codec that does this for you. My suggestion is to use the predefined websocket.Message codec to Recieve and Send messages instead.
Message is a codec to send/receive text/binary data in a frame on WebSocket connection. To send/receive text frame, use string type. To send/receive binary frame, use []byte type.
Using websocket.Message, your webHandler would look something like this:
func webHandler(ws *websocket.Conn) {
var in []byte
if err := websocket.Message.Receive(ws, &in); err != nil {
return
}
fmt.Printf("Received: %s\n", string(in))
websocket.Message.Send(ws, in)
}
And, no, it is not a requirement that Go serves the webpage. The 403 error you received does not have to do with Go or the websocket package.
I had a similar issue and the 403 error problem is related to how Go treats the http Origin header:
Handler is a simple interface to a WebSocket browser client. It checks if Origin header is valid URL by default. You might want to verify websocket.Conn.Config().Origin in the func. If you use Server instead of Handler, you could call websocket.Origin and check the origin in your Handshake func. So, if you want to accept non-browser client, which doesn't send Origin header, you could use Server . that doesn't check origin in its Handshake.
In order to disable the Origin check, you must use something like:
http.HandleFunc("/echo",
func (w http.ResponseWriter, req *http.Request) {
s := websocket.Server{Handler: websocket.Handler(webHandler)}
s.ServeHTTP(w, req)
});
At least that solved the issue for me (server to server WebSocket communication) and I think it could solve the problem as well if the origin header does not match.

Resources