I am trying to create websockets using golang with gorilla on aws (without docker) with load balancer, I have a certificate connected to the load balancer.
I managed to make the code work with http, but when I try to use the code over https it does not work.
What am I doing wrong?
When moving from http to https I changed the client request to wss instead of ws, and added the certificate to the load balancer.
Here is my code.
This is my main.go
http.HandleFunc("/wss", serveWs)
fmt.Printf("Listening on port %s\n\n", port)
if err := http.ListenAndServe(":"+port, nil); err != nil {
fmt.Printf(err.Error())
}
This is the serveWs:
func serveWs(w http.ResponseWriter, r *http.Request) {
upgrader.CheckOrigin = func(r *http.Request) bool {
// allow all connections by default
return true
}
ws, err := upgrader.Upgrade(w, r, nil)
if err != nil {
fmt.Println(err)
if _, ok := err.(websocket.HandshakeError); !ok {
log.Println(err)
}
return
}
var lastMod time.Time
if n, err := strconv.ParseInt(r.FormValue("lastMod"), 16, 64); err != nil {
lastMod = time.Unix(0, n)
}
go writer(ws, lastMod, w, r)
reader(ws)
}
This is the request:
var conn = new WebSocket("wss://https://www.weldpad.com/wss?"
When I send a request from the client i get the folloing error:
failed: Error during WebSocket handshake: Unexpected response code: 400
Looking at the server log, I see.
"could not find upgrade header with token 'websocket"
This is my load balancer configuration:
Load Balancing Configuration
I believe it should be wss://www.weldpad.com/wss? not wss://https://www.weldpad.com/wss?
Related
I am running the webserver in Go on an EC2:
package main
import (
"fmt"
"net/http"
"github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
CheckOrigin: func(r *http.Request) bool { return true },
}
func echo(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
fmt.Println(err)
return
}
defer conn.Close()
for {
msgType, msg, err := conn.ReadMessage()
if err != nil {
break
}
conn.WriteMessage(msgType, msg)
}
}
func main() {
fmt.Println("listening")
http.HandleFunc("/echo", echo)
http.ListenAndServe(":8918", nil)
}
And sending a request to it using a Python script:
import websocket
ws = websocket.WebSocket()
ws.connect("ws://myEIP:8918/echo") // redacted elastic IP
ws.send("Hello, WebSocket!")
ws.close()
However this blocks for ~30 seconds before raising an exception:
Exception has occurred: TimeoutError
[Errno 60] Operation timed out
I have my NACL set up to allow everything on port 8918, on both inbound at outbound.
I have the security group set up to allow everything on port 8918 - also outbound, but I believe security group access is stateful, so outbound isn't necessary.
I am building a dApp using #cosmjs.
I want to make a transaction on the COSMOS chain on my dApp running on the JUNO chain.
When I tried to get the signingClient, I got the following running error.
TypeError: Failed to fetch
at http (http://localhost:3000/static/js/bundle.js:53443:12)
at HttpClient.execute (http://localhost:3000/static/js/bundle.js:53471:65)
at Tendermint34Client.detectVersion (http://localhost:3000/static/js/bundle.js:55135:35)
at Tendermint34Client.create (http://localhost:3000/static/js/bundle.js:55128:33)
at Tendermint34Client.connect (http://localhost:3000/static/js/bundle.js:55115:33)
at SigningCosmWasmClient.connectWithSigner (http://localhost:3000/static/js/bundle.js:23403:64)
at http://localhost:3000/static/js/bundle.js:127476:51
at Generator.next (<anonymous>)
at fulfilled (http://localhost:3000/static/js/bundle.js:462877:24)
Here is my code;
import { SigningCosmWasmClient } from "#cosmjs/cosmwasm-stargate";
import { GasPrice }from "#cosmjs/stargate";
.....
const config = {
chainName: "Cosmos Hub",
chainId: "cosmoshub-4",
rpcEndpoint: "https://rpc-cosmoshub.whispernode.com",
restEndpoint: "",
faucetEndpoint: "",
addressPrefix: "cosmos",
microDenom: "uatom",
coinDecimals: "6",
gasPrice: "0.025",
}
.....
await window.keplr?.enable(config.chainId);
const offlineSigner= window.getOfflineSigner?.(
config.chainId
);
const account = await offlineSigner?.getAccounts();
let wasmChainClient = null;
if (offlineSigner) {
try {
wasmChainClient = await SigningCosmWasmClient.connectWithSigner(
config.rpcEndpoint,
offlineSigner,
{
gasPrice: GasPrice.fromString(
`${config.gasPrice}${config.microDenom}`
),
}
);
} catch (e) {
console.error("wallets", e);
}
}
const result= {
account: account?.[0],
client: wasmChainClient,
};
console.log(result)
Is this the problem of rpc endpoint?
I have tried other several rpc endpoints but all of them failed.
I really don't know why this happens.
I would be very thankful if anyone could help me with solving this issue.
This happens because your browser blocks request with different origin. Your origin is http://localhost:3000, and you requested https://rpc-cosmoshub.keplr.app. So, your browser blocks the response of the requested origin if there is no access-control-allow-origin header in the response. You can learn more here (https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors).
I have a workaround program that adds necessary headers to a response.
You have to have golang to run it.
package main
import (
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
)
var hostname string
var port int
func main() {
// flags declaration using flag package
flag.StringVar(&hostname, "H", "https://rpc-cosmoshub.keplr.app", "Specify hostname")
flag.IntVar(&port, "p", 8081, "Specify port")
flag.Parse() // after declaring flags we
http.HandleFunc("/", serveCorsProxy)
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", port), nil))
}
// Serve a reverse proxy for a given url
func serveCorsProxy(res http.ResponseWriter, req *http.Request) {
proxyRequest, err := http.NewRequest(req.Method, hostname, req.Body)
proxyRequest.URL.Path = req.URL.Path
proxyRequest.URL.RawQuery = req.URL.RawQuery
if err != nil {
fmt.Printf("create request error: %v", err)
return
}
response, err := http.DefaultClient.Do(proxyRequest)
if err != nil {
fmt.Printf("proxy request error: %v", err)
return
}
setHeaders(response, &res)
body, err := ioutil.ReadAll(response.Body)
if err != nil {
fmt.Printf("response read error: %v", err)
return
}
res.WriteHeader(response.StatusCode)
_, _ = res.Write(body)
}
func setHeaders(src *http.Response, dest *http.ResponseWriter) {
header := (*dest).Header()
for name, values := range (*src).Header {
for _, value := range values {
header.Set(name, value)
}
}
header.Set("access-control-allow-headers", "Accept,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With")
header.Set("access-control-allow-methods", "GET, POST, OPTIONS")
header.Set("access-control-allow-origin", "*")
header.Set("access-control-expose-headers", "Content-Length,Content-Range")
header.Set("access-control-max-age", "1728000")
}
You have to save it to file main.go and run by go run main.go -H https://rpc-cosmoshub.keplr.app -p 3001.
After that you can access the RPC on localhost:3001
How to mock redis cluster server in Golang ?
Simple redis server can be mocked using 'github.com/alicebob/miniredis' package but it does not support cluster mocking.
Received the following error:
ERR unknown command cluster, with args beginning with: slots``
My program uses 'github.com/go-redis/redis' package for redis implementation.
For example - create mock server for the following client
redisCache := redis.NewClusterClient(redisConfig)
_, err := redisCache.Ping().Result()
if err != nil {
log.Fatalf("fatal error Not able to connect using redis client: %s", err)
}
Maybe using "github.com/alicebob/miniredis/v2" instead of "github.com/alicebob/miniredis" would solve the problem.
Here's an example.
package redis_cluster_test
import (
"log"
"testing"
"time"
"github.com/alicebob/miniredis/v2"
"github.com/go-redis/redis"
)
func TestRedisCluster(t *testing.T) {
mock, err := miniredis.Run()
if err != nil {
panic(err)
}
redisConfig := redis.ClusterOptions{
Addrs: []string{mock.Addr()},
ReadTimeout: 1 * time.Second,
WriteTimeout: 1 * time.Second,
PoolSize: 6500,
PoolTimeout: 30 * time.Second}
redisCache := redis.NewClusterClient(&redisConfig)
_, err = redisCache.Ping().Result()
if err != nil {
t.Errorf("fatal error Not able to connect using redis client: %s", err)
log.Fatalf("fatal error Not able to connect using redis client: %s", err)
}
}
I am trying to make a simple demo using the fabric-sdk-go. I wonder anybod know why the code below ("client.Query") returns the error "failed to create transactor: Channel_Cfg_Cache - cache is closed"?
func initSdkClient() (*channel.Client){
sdk, err := fabsdk.New(config.FromFile("config.yaml"))
if err != nil {
logger.Fatalf("Failed to create new SDK: %s", err)
}
defer sdk.Close()
//prepare channel client context using client context
clientChannelContext := sdk.ChannelContext(channelID, fabsdk.WithUser("User1"), fabsdk.WithOrg(orgName))
// Channel client is used to query and execute transactions (Org1 is default org)
client, err := channel.New(clientChannelContext)
if err != nil {
logger.Fatalf("Failed to create new channel client: %s", err)
}
return client
}
func queryCC(client *channel.Client, targetEndpoints ...string) []byte {
response, err := client.Query(channel.Request{ChaincodeID: ccID, Fcn: "invoke", Args: defaultQueryArgs},
channel.WithRetry(retry.DefaultChannelOpts),
channel.WithTargetEndpoints(targetEndpoints...),
)
if err != nil {
***logger.Fatalf("Failed to query funds: %s", err)*** // error: failed to create transactor: Channel_Cfg_Cache - cache is closed
}
return response.Payload
}
func main() {
client := initSdkClient()
existingValue := queryCC(client)
logger.Info(existingValue)
logger.Info("hello, world\n")
}
Probably because you're closing the SDK instance at the end of initSdkClient function. Rather close the SDK at the end of main function.
Do something like
type Setup struct {
sdk *fabsdk.FabricSDK
client *channel.Client
}
func (setup *Setup) initSdkClient() *channel.Client {
sdk, err := fabsdk.New(config.FromFile("config.yaml"))
if err != nil {
fmt.Errorf("Failed to create new SDK: %s", err)
}
setup.sdk = sdk
//prepare channel client context using client context
clientChannelContext := setup.sdk.ChannelContext(channelID, fabsdk.WithUser("User1"), fabsdk.WithOrg(orgName))
// Channel client is used to query and execute transactions (Org1 is default org)
client, err := channel.New(clientChannelContext)
if err != nil {
fmt.Errorf("Failed to create new channel client: %s", err)
}
setup.client = client
return client
}
func (setup *Setup) queryCC(client *channel.Client, targetEndpoints ...string) []byte {
response, err := setup.client.Query(channel.Request{ChaincodeID: ccID, Fcn: "invoke", Args: defaultQueryArgs},
channel.WithRetry(retry.DefaultChannelOpts),
channel.WithTargetEndpoints(targetEndpoints...),
)
if err != nil {
fmt.Errorf("Failed to query funds: %s", err)
}
return response.Payload
}
func main() {
var setup Setup
client := setup.initSdkClient()
defer setup.sdk.Close()
existingValue := setup.queryCC(client)
}
I am running UT on some rest calls by creating a http test server in the Go language. My code is as follows.
type student struct{
FirstName string
LastName string
}
func testGetStudentName() {
testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
response = new(student)
response.FirstName = "Some"
response.LastName = "Name"
b, err := json.Marshal(response)
if err == nil {
fmt.Fprintln(w, string(b[:]))
}
}))
defer ts.Close()
student1 := base.getStudent("123")
log.Print("testServerUrl",testServer.URL) //prints out http://127.0.0.1:49931 ( port changes every time this is run)
ts.URL = "http://127.0.0.1:8099" //this assignment does not quite change the URL of the created test server.
}
In the file being tested,
var baseURL = "http://originalUrl.com"
var mockUrl = "http://127.0.0.1:49855"
func Init(mockServer bool){
if mockServer {
baseURL = mockUrl
}
}
func getStudent(id String){
url := baseUrl + "/student/" + id
req, err := http.NewRequest("GET", url, nil)
}
This init is called from my test.
This creates a new test server and runs the calls on a random port. Is it possible for me to run this server on a port I specify?
Most applications use the port assigned in NewServer or NewUnstartedServer because this port will not conflict with a port in use on the machine. Instead of assigning a port, they set the base URL for the service to the test server's URL.
If you do want to set the listening port, do the following:
// create a listener with the desired port.
l, err := net.Listen("tcp", "127.0.0.1:8080")
if err != nil {
log.Fatal(err)
}
ts := httptest.NewUnstartedServer(handler)
// NewUnstartedServer creates a listener. Close that listener and replace
// with the one we created.
ts.Listener.Close()
ts.Listener = l
// Start the server.
ts.Start()
// Stop the server on return from the function.
defer ts.Close()
// Add your test code here.