我已经使用了 Go 的 net/rpc 和 net/rpc/jsonrpc 包来执行 Go 进程之间的连接,但是我想知道是否有仅使用标准库中的服务器工具连接到 HTTP JSONRPC 服务器的方法(并不是说我自己编写有问题,只是如果不需要的话不想这样做)。
这是我的基本服务器设置:
arith := new(server.Arith)
server := rpc.NewServer()
server.Register(arith)
server.HandleHTTP(rpc.DefaultRPCPath, rpc.DefaultDebugPath)
listener, e := net.Listen("tcp", ":4321")
if e != nil {
log.Fatal("listen error:", e)
}
defer listener.Close()
http.Serve(listener, http.DefaultServeMux)
我希望能够从网页或简单的命令行 CURL 调用中实现这一点——只是一个普通的 POST。
但是,这一行:http://golang.org/src/net/rpc/server.go?s=20445:20475#L670似乎表明它希望 HTTP 客户端发出 CONNECT,然后直接将 JSON RPC 请求写入流并以相同的方式接收回复。我不知道这是否可以通过浏览器实现,但它肯定不像简单的 POST 那样普遍或兼容。
有没有一种方法可以启动一个 JSON RPC 服务器,我可以使用好的 XMLHttpRequest 将其 POST 到?
编辑:废话 - 上面甚至没有使用 jsonrpc 东西 - 这可能是在尝试使用 Gob,但无论如何 - 问题是一样的 - src/net/rpc/server.go 中的代码不会处理 POST,因此无论服务器编解码器如何,这条路线总体上都不会起作用。
最佳答案
FWIW,我通过制作一个简单的 HTTP 处理程序使 HTTP 请求/响应适应 ServerCodec 来实现这一点。似乎很有魅力。
这是作为测试的工作代码:
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"log"
"net"
"net/http"
"net/rpc"
"net/rpc/jsonrpc"
"testing"
)
// adapt HTTP connection to ReadWriteCloser
type HttpConn struct {
in io.Reader
out io.Writer
}
func (c *HttpConn) Read(p []byte) (n int, err error) { return c.in.Read(p) }
func (c *HttpConn) Write(d []byte) (n int, err error) { return c.out.Write(d) }
func (c *HttpConn) Close() error { return nil }
// our service
type CakeBaker struct{}
func (cb *CakeBaker) BakeIt(n int, msg *string) error {
*msg = fmt.Sprintf("your cake has been bacon (%d)", n)
return nil
}
func TestHTTPServer(t *testing.T) {
fmt.Printf("TestHTTPServer\n")
cb := &CakeBaker{}
server := rpc.NewServer()
server.Register(cb)
listener, e := net.Listen("tcp", ":4321")
if e != nil {
log.Fatal("listen error:", e)
}
defer listener.Close()
go http.Serve(listener, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/bake-me-a-cake" {
serverCodec := jsonrpc.NewServerCodec(&HttpConn{in: r.Body, out: w})
w.Header().Set("Content-type", "application/json")
w.WriteHeader(200)
err := server.ServeRequest(serverCodec)
if err != nil {
log.Printf("Error while serving JSON request: %v", err)
http.Error(w, "Error while serving JSON request, details have been logged.", 500)
return
}
}
}))
resp, err := http.Post("http://localhost:4321/bake-me-a-cake", "application/json", bytes.NewBufferString(
`{"jsonrpc":"2.0","id":1,"method":"CakeBaker.BakeIt","params":[10]}`,
))
if err != nil {
panic(err)
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Printf("returned JSON: %s\n", string(b))
}
关于json - golang http+jsonrpc 网页访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31396924/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以
在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这
我有一个非常简单的RubyRack服务器,例如:app=Proc.newdo|env|req=Rack::Request.new(env).paramspreq.inspect[200,{'Content-Type'=>'text/plain'},['Somebody']]endRack::Handler::Thin.run(app,:Port=>4001,:threaded=>true)每当我使用JSON对象向服务器发送POSTHTTP请求时:{"session":{"accountId":String,"callId":String,"from":Object,"headers":
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
我正在使用ruby2.1.0我有一个json文件。例如:test.json{"item":[{"apple":1},{"banana":2}]}用YAML.load加载这个文件安全吗?YAML.load(File.read('test.json'))我正在尝试加载一个json或yaml格式的文件。 最佳答案 YAML可以加载JSONYAML.load('{"something":"test","other":4}')=>{"something"=>"test","other"=>4}JSON将无法加载YAML。JSON.load("
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
我想从then子句中访问case语句表达式,即food="cheese"casefoodwhen"dip"then"carrotsticks"when"cheese"then"#{expr}crackers"else"mayo"end在这种情况下,expr是食物的当前值(value)。在这种情况下,我知道,我可以简单地访问变量food,但是在某些情况下,该值可能无法再访问(array.shift等)。除了将expr移出到局部变量然后访问它之外,是否有直接访问caseexpr值的方法?罗亚附注我知道这个具体示例很简单,只是一个示例场景。 最佳答案