What is the function of each query string (EIO, transport, t) passed during each socket io connection request? And how to generate the t value?
Related
// Body is the request's body.
//
// For client requests, a nil body means the request has no
// body, such as a GET request. The HTTP Client's Transport
// is responsible for calling the Close method.
//
// For server requests, the Request Body is always non-nil
// but will return EOF immediately when no body is present.
// The Server will close the request body. The ServeHTTP
// Handler does not need to.
//
// Body must allow Read to be called concurrently with Close.
// In particular, calling Close should unblock a Read waiting
// for input.
Body io.ReadCloser
According to the document of http.Request, the Body must allow Read to be called concurrently with Close. In particular, calling Close should unblock a Read waiting for input.
I would like to use the return value of os.Open() directly as the Body of a http.Request like this:
file, _ := os.Open("example.md")
http.DefaultClient.Do(&http.Request{
Body: file,
})
Is that appropriate? Does os.File meet the requirement "must allow Read to be called concurrently with Close. In particular, calling Close should unblock a Read waiting for input"?
I'd appreciate it if someone could help me out!
I found the following code
client := &http.Client
What does & mean? What kind of value that client var receives
& is the "pointer to" operator, similar to c. The client variable holds a pointer to the value of http.Client.
client here is a pointer to the instance of http.Client.
It is same as:
var client *http.Client
client = &http.Client{...}
I'm trying to write code to stream data on a topic, like a radio station (one broadcaster, several listeners). I'm stuck on how to process a new WebSocket connection request without having a goroutine for each open WebSocket (that starts to get resource-intensive for many "listeners" to the same "station").
At the moment, I have a map of dataStream structs which look like this:
struct dataStream {
data chan byte[]
conns []*websocket.Connection
}
And here's the pseudocode for upgrading the request to a WebSocket, and then attempting to add a WebSocket connection to the dataStreams conns:
func process_request(w http.ResponseWriter, r *http.Request) {
// hundred lines of business logic...
c := upgrade websocket connection
defer c.Close()
if dataStream exists {
append the new connection c to the dataStream.conns slice
} else {
create new dataStream
append the new connection c to the dataStream.conns slice
stream(dataStream)
}
}
And then here's the stream function mentioned in the above code block. One of these runs in the background for each dataStream (not for every WebSocket connection).
func stream(ds *dataStream) {
ticker := time.NewTicker(poll every ~10 seconds)
go func() { // this is to poll and remove closed connections
for _ = range ticker.C {
for traverse ds.conns {
ping all connections, remove any closed ones and free memory
if len(ds.conns == 0){ // no more connections are listening to this dataStream
delete the ds dataStream and free the memory
stop ticker
return // kill goroutine and free the memory
}
}
}}()
while len(ds.conns) != 0 { // while there are open connections
fetch any available <-ds.data from channel
write the data as websocket message to each connection
}
}
The trouble with this approach is that in the process_request function, as soon as the flow reaches the bottom if statement of the 2nd and subsequent connections, after the new connection is appended to the dataStream.conns slice the function terminates closing the WebSocket connection! As a result, stream() is running in the background and polls that a closed connection has been added to the ds.conns slice and removes it.
Hence my question:
What approach should I take to maintain the WebSocket connection open for even after the process_request handler function returns, preferentially without running a separate goroutine for each connection?
The application must explicitly close a Gorilla connection. The connection is not automatically closed when the HTTP handler function returns.
In this case, the application uses a defer statement to close the connection on return from the handler. Delete the defer statement to avoid closing the connection.
I have an RPC system, where the interface used for the result is as follows:
type ValReply struct {
Val string
}
Sometimes, my RPC will set reply.Val to ""(the empty string). In these cases, the previous value in reply.Val is not overwritten, leaving the incorrect result to be used by the client.
How can I get my RPC call to return an empty string?
I have googled this issue, and I can't find anything about not returning empty strings in the RPC API.
"" (the empty string) is often interpreted by libraries (database, rpc, json) as the default value and just ignored.
To get more control over nil, and "", change the rpc signature to:
type ValReply struct {
Val *string
}
and then the library will distinguish empty, from null etc.
I was reading the type declaration for http.Server in the documentation and I came across this.
type Server struct {
Addr string // TCP address to listen on, ":http" if empty
// more...
}
If you call srv.ListenAndServe() and srv.Addr is an empty string, then ListenAndServe will pass ":http" to net.Listen (http/server.go).
What does ":http" mean?
Sometimes ports have aliases. http is 80.You can see more names here: http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml