This commit is contained in:
Dmitry Maksimov 2014-03-06 23:44:08 +04:00
Родитель 923b8036fe
Коммит dac4f80439
7 изменённых файлов: 111 добавлений и 23 удалений

Просмотреть файл

@ -32,8 +32,8 @@ type clientCodec struct {
ready chan uint64 ready chan uint64
} }
func (codec *clientCodec) WriteRequest(request *rpc.Request, params interface{}) (err error) { func (codec *clientCodec) WriteRequest(request *rpc.Request, args interface{}) (err error) {
httpRequest, err := NewRequest(codec.url, request.ServiceMethod, params) httpRequest, err := NewRequest(codec.url, request.ServiceMethod, args)
if codec.cookies != nil { if codec.cookies != nil {
for _, cookie := range codec.cookies { for _, cookie := range codec.cookies {

Просмотреть файл

@ -1 +1,69 @@
package xmlrpc package xmlrpc
import (
"time"
"testing"
)
func Test_CallWithoutArgs(t *testing.T) {
client := newClient(t)
defer client.Close()
var result time.Time
if err := client.Call("service.time", nil, &result); err != nil {
t.Fatalf("service.time call error: %v", err)
}
}
func Test_CallWithOneArg(t *testing.T) {
client := newClient(t)
defer client.Close()
var result string
if err := client.Call("service.upcase", "xmlrpc", &result); err != nil {
t.Fatalf("service.upcase call error: %v", err)
}
if result != "XMLRPC" {
t.Fatalf("Unexpected result of service.upcase: %s != %s", "XMLRPC", result)
}
}
func Test_CallWithTwoArgs(t *testing.T) {
client := newClient(t)
defer client.Close()
var sum int
if err := client.Call("service.sum", []interface{}{2,3}, &sum); err != nil {
t.Fatalf("service.upcase call error: %v", err)
}
if sum != 5 {
t.Fatalf("Unexpected result of service.sum: %d != %d", 5, sum)
}
}
func Test_TwoCalls(t *testing.T) {
client := newClient(t)
defer client.Close()
var upcase string
if err := client.Call("service.upcase", "xmlrpc", &upcase); err != nil {
t.Fatalf("service.upcase call error: %v", err)
}
var sum int
if err := client.Call("service.sum", []interface{}{2,3}, &sum); err != nil {
t.Fatalf("service.upcase call error: %v", err)
}
}
func newClient(t *testing.T) *Client {
client, err := NewClient("http://localhost:5001", nil)
if err != nil {
t.Fatalf("Can't create client: %v", err)
}
return client
}

Просмотреть файл

@ -11,7 +11,7 @@ import (
"time" "time"
) )
const TIME_LAYOUT = "20060102T15:04:05" const iso8601 = "20060102T15:04:05"
var ( var (
invalidXmlError = errors.New("invalid xml") invalidXmlError = errors.New("invalid xml")
@ -212,7 +212,7 @@ func (dec *decoder) decodeValue(val reflect.Value) error {
case "string": case "string":
val.SetString(string(data)) val.SetString(string(data))
case "dateTime.iso8601": case "dateTime.iso8601":
t, err := time.Parse(TIME_LAYOUT, string(data)) t, err := time.Parse(iso8601, string(data))
if err != nil { if err != nil {
return err return err
} }

Просмотреть файл

@ -12,6 +12,10 @@ import (
type encodeFunc func(reflect.Value) ([]byte, error) type encodeFunc func(reflect.Value) ([]byte, error)
func marshal(v interface{}) ([]byte, error) { func marshal(v interface{}) ([]byte, error) {
if v == nil {
return []byte{}, nil
}
val := reflect.ValueOf(v) val := reflect.ValueOf(v)
return encodeValue(val) return encodeValue(val)
} }
@ -33,8 +37,7 @@ func encodeValue(val reflect.Value) ([]byte, error) {
switch val.Interface().(type) { switch val.Interface().(type) {
case time.Time: case time.Time:
t := val.Interface().(time.Time) t := val.Interface().(time.Time)
b = []byte(fmt.Sprintf("<dateTime.iso8601>%s</dateTime.iso8601>", b = []byte(fmt.Sprintf("<dateTime.iso8601>%s</dateTime.iso8601>", t.Format(iso8601)))
t.Format(time.RFC3339)))
default: default:
b, err = encodeStruct(val) b, err = encodeStruct(val)
} }

Просмотреть файл

@ -16,7 +16,7 @@ var marshalTests = []struct {
{false, "<value><boolean>0</boolean></value>"}, {false, "<value><boolean>0</boolean></value>"},
{12.134, "<value><double>12.134</double></value>"}, {12.134, "<value><double>12.134</double></value>"},
{-12.134, "<value><double>-12.134</double></value>"}, {-12.134, "<value><double>-12.134</double></value>"},
{time.Unix(1386622812, 0).UTC(), "<value><dateTime.iso8601>2013-12-09T21:00:12Z</dateTime.iso8601></value>"}, {time.Unix(1386622812, 0).UTC(), "<value><dateTime.iso8601>20131209T21:00:12</dateTime.iso8601></value>"},
{[]interface{}{1,"one"}, "<value><array><value><int>1</int></value><value><string>one</string></value></array></value>"}, {[]interface{}{1,"one"}, "<value><array><value><int>1</int></value><value><string>one</string></value></array></value>"},
{&struct{ {&struct{
Title string Title string

Просмотреть файл

@ -6,8 +6,8 @@ import (
"net/http" "net/http"
) )
func NewRequest(url string, method string, params ...interface{}) (*http.Request, error) { func NewRequest(url string, method string, args interface{}) (*http.Request, error) {
body, err := EncodeRequest(method, params) body, err := EncodeRequest(method, args)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -23,26 +23,42 @@ func NewRequest(url string, method string, params ...interface{}) (*http.Request
return request, nil return request, nil
} }
func EncodeRequest(method string, params []interface{}) ([]byte, error) { func EncodeRequest(method string, args interface{}) ([]byte, error) {
buf := bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?>`) buf := bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?>`)
var err error var err error
if _, err = fmt.Fprintf(buf, "<methodCall><methodName>%s</methodName><params>", method); err != nil { if _, err = fmt.Fprintf(buf, "<methodCall><methodName>%s</methodName>", method); err != nil {
return nil, err return nil, err
} }
for _, p := range params { if args != nil {
b, err := marshal(p) if _, err = fmt.Fprintf(buf, "<params>"); err != nil {
return nil, err
}
var t []interface{}
var ok bool
if t, ok = args.([]interface{}); !ok {
t = []interface{}{args}
}
for _, arg := range t {
b, err := marshal(arg)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if _, err = fmt.Fprintf(buf, "<param>%v</param>", b); err != nil { if _, err = fmt.Fprintf(buf, "<param>%s</param>", string(b)); err != nil {
return nil, err return nil, err
} }
} }
if _, err = buf.WriteString("</params></methodCall>"); err != nil { if _, err = fmt.Fprintf(buf, "</params>"); err != nil {
return nil, err
}
}
if _, err = buf.WriteString("</methodCall>"); err != nil {
return nil, err return nil, err
} }

Просмотреть файл

@ -2,23 +2,24 @@
require "xmlrpc/server" require "xmlrpc/server"
class Bugzilla class Service
def time def time
puts "#time"
Time.now Time.now
end end
def login(opts) def upcase(s)
puts "#login" s.upcase
{id: 120} end
def sum(x, y)
x + y
end end
def error def error
puts "#error"
raise XMLRPC::FaultException.new(101, "Error occuried.") raise XMLRPC::FaultException.new(101, "Error occuried.")
end end
end end
server = XMLRPC::Server.new 5001, 'localhost' server = XMLRPC::Server.new 5001, 'localhost'
server.add_handler "bugzilla", Bugzilla.new server.add_handler "service", Service.new
server.serve server.serve