Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
whqwjb
go-ethereum
提交
290d6bd9
G
go-ethereum
项目概览
whqwjb
/
go-ethereum
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
go-ethereum
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
290d6bd9
编写于
8月 03, 2020
作者:
R
rene
提交者:
GitHub
8月 03, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
rpc: add SetHeader method to Client (#21392)
Resolves #20163 Co-authored-by:
N
Felix Lange
<
fjl@twurst.com
>
上级
9c2ac6fb
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
79 addition
and
10 deletion
+79
-10
rpc/client.go
rpc/client.go
+14
-1
rpc/client_test.go
rpc/client_test.go
+37
-0
rpc/http.go
rpc/http.go
+28
-9
未找到文件。
rpc/client.go
浏览文件 @
290d6bd9
...
@@ -85,7 +85,7 @@ type Client struct {
...
@@ -85,7 +85,7 @@ type Client struct {
// writeConn is used for writing to the connection on the caller's goroutine. It should
// writeConn is used for writing to the connection on the caller's goroutine. It should
// only be accessed outside of dispatch, with the write lock held. The write lock is
// only be accessed outside of dispatch, with the write lock held. The write lock is
// taken by sending on req
uestOp and released by sending on sendDone
.
// taken by sending on req
Init and released by sending on reqSent
.
writeConn
jsonWriter
writeConn
jsonWriter
// for dispatch
// for dispatch
...
@@ -260,6 +260,19 @@ func (c *Client) Close() {
...
@@ -260,6 +260,19 @@ func (c *Client) Close() {
}
}
}
}
// SetHeader adds a custom HTTP header to the client's requests.
// This method only works for clients using HTTP, it doesn't have
// any effect for clients using another transport.
func
(
c
*
Client
)
SetHeader
(
key
,
value
string
)
{
if
!
c
.
isHTTP
{
return
}
conn
:=
c
.
writeConn
.
(
*
httpConn
)
conn
.
mu
.
Lock
()
conn
.
headers
.
Set
(
key
,
value
)
conn
.
mu
.
Unlock
()
}
// Call performs a JSON-RPC call with the given arguments and unmarshals into
// Call performs a JSON-RPC call with the given arguments and unmarshals into
// result if no error occurred.
// result if no error occurred.
//
//
...
...
rpc/client_test.go
浏览文件 @
290d6bd9
...
@@ -26,6 +26,7 @@ import (
...
@@ -26,6 +26,7 @@ import (
"os"
"os"
"reflect"
"reflect"
"runtime"
"runtime"
"strings"
"sync"
"sync"
"testing"
"testing"
"time"
"time"
...
@@ -429,6 +430,42 @@ func TestClientNotificationStorm(t *testing.T) {
...
@@ -429,6 +430,42 @@ func TestClientNotificationStorm(t *testing.T) {
doTest
(
23000
,
true
)
doTest
(
23000
,
true
)
}
}
func
TestClientSetHeader
(
t
*
testing
.
T
)
{
var
gotHeader
bool
srv
:=
newTestServer
()
httpsrv
:=
httptest
.
NewServer
(
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
if
r
.
Header
.
Get
(
"test"
)
==
"ok"
{
gotHeader
=
true
}
srv
.
ServeHTTP
(
w
,
r
)
}))
defer
httpsrv
.
Close
()
defer
srv
.
Stop
()
client
,
err
:=
Dial
(
httpsrv
.
URL
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
defer
client
.
Close
()
client
.
SetHeader
(
"test"
,
"ok"
)
if
_
,
err
:=
client
.
SupportedModules
();
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
!
gotHeader
{
t
.
Fatal
(
"client did not set custom header"
)
}
// Check that Content-Type can be replaced.
client
.
SetHeader
(
"content-type"
,
"application/x-garbage"
)
_
,
err
=
client
.
SupportedModules
()
if
err
==
nil
{
t
.
Fatal
(
"no error for invalid content-type header"
)
}
else
if
!
strings
.
Contains
(
err
.
Error
(),
"Unsupported Media Type"
)
{
t
.
Fatalf
(
"error is not related to content-type: %q"
,
err
)
}
}
func
TestClientHTTP
(
t
*
testing
.
T
)
{
func
TestClientHTTP
(
t
*
testing
.
T
)
{
server
:=
newTestServer
()
server
:=
newTestServer
()
defer
server
.
Stop
()
defer
server
.
Stop
()
...
...
rpc/http.go
浏览文件 @
290d6bd9
...
@@ -26,6 +26,7 @@ import (
...
@@ -26,6 +26,7 @@ import (
"io/ioutil"
"io/ioutil"
"mime"
"mime"
"net/http"
"net/http"
"net/url"
"sync"
"sync"
"time"
"time"
)
)
...
@@ -40,9 +41,11 @@ var acceptedContentTypes = []string{contentType, "application/json-rpc", "applic
...
@@ -40,9 +41,11 @@ var acceptedContentTypes = []string{contentType, "application/json-rpc", "applic
type
httpConn
struct
{
type
httpConn
struct
{
client
*
http
.
Client
client
*
http
.
Client
req
*
http
.
Request
url
string
closeOnce
sync
.
Once
closeOnce
sync
.
Once
closeCh
chan
interface
{}
closeCh
chan
interface
{}
mu
sync
.
Mutex
// protects headers
headers
http
.
Header
}
}
// httpConn is treated specially by Client.
// httpConn is treated specially by Client.
...
@@ -51,7 +54,7 @@ func (hc *httpConn) writeJSON(context.Context, interface{}) error {
...
@@ -51,7 +54,7 @@ func (hc *httpConn) writeJSON(context.Context, interface{}) error {
}
}
func
(
hc
*
httpConn
)
remoteAddr
()
string
{
func
(
hc
*
httpConn
)
remoteAddr
()
string
{
return
hc
.
req
.
URL
.
String
()
return
hc
.
url
}
}
func
(
hc
*
httpConn
)
readBatch
()
([]
*
jsonrpcMessage
,
bool
,
error
)
{
func
(
hc
*
httpConn
)
readBatch
()
([]
*
jsonrpcMessage
,
bool
,
error
)
{
...
@@ -102,16 +105,24 @@ var DefaultHTTPTimeouts = HTTPTimeouts{
...
@@ -102,16 +105,24 @@ var DefaultHTTPTimeouts = HTTPTimeouts{
// DialHTTPWithClient creates a new RPC client that connects to an RPC server over HTTP
// DialHTTPWithClient creates a new RPC client that connects to an RPC server over HTTP
// using the provided HTTP Client.
// using the provided HTTP Client.
func
DialHTTPWithClient
(
endpoint
string
,
client
*
http
.
Client
)
(
*
Client
,
error
)
{
func
DialHTTPWithClient
(
endpoint
string
,
client
*
http
.
Client
)
(
*
Client
,
error
)
{
req
,
err
:=
http
.
NewRequest
(
http
.
MethodPost
,
endpoint
,
nil
)
// Sanity check URL so we don't end up with a client that will fail every request.
_
,
err
:=
url
.
Parse
(
endpoint
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
req
.
Header
.
Set
(
"Content-Type"
,
contentType
)
req
.
Header
.
Set
(
"Accept"
,
contentType
)
initctx
:=
context
.
Background
()
initctx
:=
context
.
Background
()
headers
:=
make
(
http
.
Header
,
2
)
headers
.
Set
(
"accept"
,
contentType
)
headers
.
Set
(
"content-type"
,
contentType
)
return
newClient
(
initctx
,
func
(
context
.
Context
)
(
ServerCodec
,
error
)
{
return
newClient
(
initctx
,
func
(
context
.
Context
)
(
ServerCodec
,
error
)
{
return
&
httpConn
{
client
:
client
,
req
:
req
,
closeCh
:
make
(
chan
interface
{})},
nil
hc
:=
&
httpConn
{
client
:
client
,
headers
:
headers
,
url
:
endpoint
,
closeCh
:
make
(
chan
interface
{}),
}
return
hc
,
nil
})
})
}
}
...
@@ -131,7 +142,7 @@ func (c *Client) sendHTTP(ctx context.Context, op *requestOp, msg interface{}) e
...
@@ -131,7 +142,7 @@ func (c *Client) sendHTTP(ctx context.Context, op *requestOp, msg interface{}) e
if
respBody
!=
nil
{
if
respBody
!=
nil
{
buf
:=
new
(
bytes
.
Buffer
)
buf
:=
new
(
bytes
.
Buffer
)
if
_
,
err2
:=
buf
.
ReadFrom
(
respBody
);
err2
==
nil
{
if
_
,
err2
:=
buf
.
ReadFrom
(
respBody
);
err2
==
nil
{
return
fmt
.
Errorf
(
"%v %v"
,
err
,
buf
.
String
())
return
fmt
.
Errorf
(
"%v
:
%v"
,
err
,
buf
.
String
())
}
}
}
}
return
err
return
err
...
@@ -166,10 +177,18 @@ func (hc *httpConn) doRequest(ctx context.Context, msg interface{}) (io.ReadClos
...
@@ -166,10 +177,18 @@ func (hc *httpConn) doRequest(ctx context.Context, msg interface{}) (io.ReadClos
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
req
:=
hc
.
req
.
WithContext
(
ctx
)
req
,
err
:=
http
.
NewRequestWithContext
(
ctx
,
"POST"
,
hc
.
url
,
ioutil
.
NopCloser
(
bytes
.
NewReader
(
body
)))
req
.
Body
=
ioutil
.
NopCloser
(
bytes
.
NewReader
(
body
))
if
err
!=
nil
{
return
nil
,
err
}
req
.
ContentLength
=
int64
(
len
(
body
))
req
.
ContentLength
=
int64
(
len
(
body
))
// set headers
hc
.
mu
.
Lock
()
req
.
Header
=
hc
.
headers
.
Clone
()
hc
.
mu
.
Unlock
()
// do request
resp
,
err
:=
hc
.
client
.
Do
(
req
)
resp
,
err
:=
hc
.
client
.
Do
(
req
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录