我想监听多个传输编码响应的 HTTP 流,然后逐行从中获取消息,然后将消息推送到一个 channel 。然后我想从 channel 中读取并稍后通过 websocket 推送。
func subscribe(ws chan<- string, group string) (scanner *bufio.Scanner, err error){
res, _ := req(STREAM_URL, channelTemplate(group))
reader := bufio.NewScanner(res.Body)
return reader, reader.Err()
}
func main() {
ws := make(chan string)
request, _ := http.NewRequest("GET", URL, nil)
request.Header.Add("Content-Type", "application/json")
client := &http.Client{}
resp, _ := client.Do(request)
ac := ACResponse{}
json.NewDecoder(resp.Body).Decode(&ac)
resp.Body.Close()
var scanners = make([]*bufio.Scanner, 0)
for _, group := range ac.Groups {
fmt.Println("Started worker for", group)
//listen to all stream URLs
scanner, err := subscribe(ws, group)
if err != nil {
panic(err)
}
// keep track of Scanner to read later
scanners = append(scanners, scanner)
}
for {
select {
case msg := <-ws:
fmt.Println("[events] ", msg)
default:
randScanner := rand.Intn(len(ac.Groups)-1)
fmt.Println("Reading from", randScanner)
reader := scanners[randScanner]
reader.Scan()
if err := reader.Err(); err != nil {
panic(err)
}
text := reader.Text()
ws <- text
}
}
}
程序在 reader.Scan() 处阻塞。输出是 Reading from 1 而不是别的。我查看了 wireshark,消息正在通过。
如何使用 Go 更好地设计这个问题?
最佳答案
主要 block 发送到无缓冲 channel ws。要解决此问题,请将 ws 更改为缓冲 channel :
ws := make(chan string, 1)
第二个问题是 main() 在到达 EOF 后继续读取扫描仪。问题出在这些行上:
reader.Scan()
if err := reader.Err(); err != nil {
panic(err)
}
text := reader.Text()
Scan() 在 EOF 处返回 false,但忽略 scan 的返回。 Err() 在 EOF 时返回 nil。修改应用程序以使用 Scan() 的返回值。
还有一个问题是任何一个扫描器读取时的主要 block 。为了避免在单个连接上阻塞,启动一个 goroutine 来读取每个连接:
func subscribe(wg *sync.WaitGroup, ws chan<- string, group string) {
defer wg.Done()
res, err := req(STREAM_URL, channelTemplate(group))
if err ! nil {
// handle error
}
defer resp.Body.Close()
reader := bufio.NewScanner(res.Body)
for reader.Scan() {
ws <- reader.Text()
}
if err := reader.Err(); err != nil {
// handle error
}
}
func main() {
ws := make(chan string)
request, _ := http.NewRequest("GET", URL, nil)
request.Header.Add("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(request)
if err != nil {
// handle error
}
var ac ACResponse
if err := json.NewDecoder(resp.Body).Decode(&ac); err != nil {
// handle error
}
resp.Body.Close()
var wg sync.WaitGroup
for _, group := range ac.Groups {
wg.Add(1)
go subscribe(&wg, ws, group)
}
go func() {
wg.Wait()
close(ws)
}()
for msg := range ws {
fmt.Println("[events] ", msg)
}
}
以上代码未经编译和测试。我已经标记了需要错误处理的地方。我编写了在所有连接到达 EOF 后退出 main 的代码。这可能是也可能不是您在应用程序中想要的。
关于go - HTTP Chunked 流式传输到 WebSocket,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35350204/
我有一个super简单的脚本,它几乎包含了FayeWebSocketGitHub页面上用于处理关闭连接的内容:ws=Faye::WebSocket::Client.new(url,nil,:headers=>headers)ws.on:opendo|event|p[:open]#sendpingcommand#sendtestcommand#ws.send({command:'test'}.to_json)endws.on:messagedo|event|#hereistheentrypointfordatacomingfromtheserver.pJSON.parse(event.d
在Railcasts上,我注意到一个非常有趣的功能“转到符号”窗口。它像Command-T一样工作,但显示当前文件中可用的类和方法。如何在vim中获取它? 最佳答案 尝试:helptags有各种程序和脚本可以生成标记文件。此外,标记文件格式非常简单,因此很容易将sed(1)或类似的脚本组合在一起,无论您使用何种语言,它们都可以生成标记文件。轻松获取标记文件(除了下载生成器之外)的关键在于格式化样式而不是实际解析语法。 关于ruby-on-rails-Textmate'Gotosymbol
IntrductionLibwebsocketsisasimple-to-use,MIT-license,pureClibraryprovidingclientandserverforhttp/1,http/2,websockets,MQTTandotherprotocolsinasecurity-minded,lightweight,configurable,scalableandflexibleway.It’seasytobuildandcross-buildviacmakeandissuitablefortasksfromembeddedRTOSthroughmasscloudservi
我想通过Sinatra应用程序代理远程文件。这需要将带有header的HTTP响应从远程源流式传输回客户端,但我不知道如何在Net::HTTP#提供的block内使用流式API时设置响应header获取响应。例如,这不会设置响应头:get'/file'dostreamdo|out|uri=URI("http://manuals.info.apple.com/en/ipad_user_guide.pdf")Net::HTTP.get_response(uri)do|file|headers'Content-Type'=>file.header['Content-Type']file.re
我正在尝试下载一个大文件,然后使用Ruby将该文件发布到REST端点。该文件可能非常大,即超过可以存储在内存中甚至磁盘上的临时文件中的容量。我一直在用Net::HTTP尝试这个,但我愿意接受任何其他库(rest-client等)的解决方案,只要他们做我想做的事情。这是我尝试过的:require'net/http'source_uri=URI("https://example.org/very_large_file")source_request=Net::HTTP::Get.new(source_uri)source_http=Net::HTTP.start(source_uri.ho
我在Heroku上构建了一个必须在Docker容器内运行的RoR应用程序。为此,我使用officialDockerfile.因为它在Heroku中很常见,所以我需要一些附加组件才能使这个应用程序完全运行。在生产中,变量DATABASE_URL在我的应用程序中可用。但是,如果我尝试其他一些使用环境变量(在我的例子中是Mailtrap)的加载项,变量不会在运行时复制到实例中。所以我的问题很简单:如何让docker实例在Heroku上执行时知道环境变量?您可能会问,我已经知道我们可以在docker-compose.yml中指定一个environment指令。我想避免这种情况,以便能够通过项目
我有带有gemwebsocket-rails0.7的Rails3.2应用程序。在开发机上,一切正常在生产环境中,我使用Nginx/1.6作为代理服务器,Unicorn作为http服务器。Thin用于独立模式(在https://github.com/websocket-rails/websocket-rails/wiki/Standalone-Server-Mode之后)。nginx配置:location/websocket{proxy_passhttp://localhost:3001/websocket;proxy_http_version1.1;proxy_set_headerUp
在aws-s3中,有一种方法(AWS::S3::S3Object.stream)可让您将S3上的文件流式传输到本地文件。我无法在aws-sdk中找到类似的方法。即在aws-s3中,我这样做:File.open(to_file,"wb")do|file|AWS::S3::S3Object.stream(key,region)do|chunk|file.writechunkendendAWS::S3:S3Object.read方法确实将block作为参数,但似乎没有对其执行任何操作。 最佳答案 aws-sdkgem现在支持S3中对象的分
目录一、什么是Websocket二、WebSocket部分header介绍三、HTTPVSWebSocket四、什么时候使用WebSockets五、关于SockJS和STOMP一、什么是Websocket根据RFC6455标准,Websocket协议提供了一种标准化的方式在客户端和服务端之间通过TCP连接建立全双工、双向通信渠道。它是一种不同于HTTP的TCP协议,但是被设计为在HTTP基础上运行。Websocket交互始于HTTP请求,该请求会通过HTTPUpgrade请求头去升级请求,进而切换到Websocket协议。请求报文如下:GET/spring-websocket-portfoli
似乎Capistrano曾经有anextensivefiletransferpackage.但是在3.0版本重写后好像没有了。知道是否还有其他方法可以将文件传输到服务器/从服务器传输文件吗? 最佳答案 下载:desc"downloadfoobar.txtintolocal_dir/"task:foobardodownload!"some_remote_path/foobar.txt","local_dir/"end我知道这从Cap3.2.1开始有效,因为我现在正在使用它。 关于ruby-