github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/p2p/simulations/http.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有2017 Go Ethereum作者 10 //此文件是Go以太坊库的一部分。 11 // 12 //Go-Ethereum库是免费软件:您可以重新分发它和/或修改 13 //根据GNU发布的较低通用公共许可证的条款 14 //自由软件基金会,或者许可证的第3版,或者 15 //(由您选择)任何更高版本。 16 // 17 //Go以太坊图书馆的发行目的是希望它会有用, 18 //但没有任何保证;甚至没有 19 //适销性或特定用途的适用性。见 20 //GNU较低的通用公共许可证,了解更多详细信息。 21 // 22 //你应该收到一份GNU较低级别的公共许可证副本 23 //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。 24 25 package simulations 26 27 import ( 28 "bufio" 29 "bytes" 30 "context" 31 "encoding/json" 32 "fmt" 33 "io" 34 "io/ioutil" 35 "net/http" 36 "strconv" 37 "strings" 38 "sync" 39 40 "github.com/ethereum/go-ethereum/event" 41 "github.com/ethereum/go-ethereum/p2p" 42 "github.com/ethereum/go-ethereum/p2p/discover" 43 "github.com/ethereum/go-ethereum/p2p/simulations/adapters" 44 "github.com/ethereum/go-ethereum/rpc" 45 "github.com/julienschmidt/httprouter" 46 "golang.org/x/net/websocket" 47 ) 48 49 //DefaultClient是默认的模拟API客户端,它需要API 50 //在http://localhost:8888上运行 51 var DefaultClient = NewClient("http://本地主机:8888“) 52 53 //客户端是支持创建的模拟HTTP API的客户端 54 //以及管理模拟网络 55 type Client struct { 56 URL string 57 58 client *http.Client 59 } 60 61 //new client返回新的模拟API客户端 62 func NewClient(url string) *Client { 63 return &Client{ 64 URL: url, 65 client: http.DefaultClient, 66 } 67 } 68 69 //GetNetwork返回网络的详细信息 70 func (c *Client) GetNetwork() (*Network, error) { 71 network := &Network{} 72 return network, c.Get("/", network) 73 } 74 75 //StartNetwork启动模拟网络中的所有现有节点 76 func (c *Client) StartNetwork() error { 77 return c.Post("/start", nil, nil) 78 } 79 80 //stopNetwork停止模拟网络中的所有现有节点 81 func (c *Client) StopNetwork() error { 82 return c.Post("/stop", nil, nil) 83 } 84 85 //创建快照创建网络快照 86 func (c *Client) CreateSnapshot() (*Snapshot, error) { 87 snap := &Snapshot{} 88 return snap, c.Get("/snapshot", snap) 89 } 90 91 //LoadSnapshot将快照加载到网络中 92 func (c *Client) LoadSnapshot(snap *Snapshot) error { 93 return c.Post("/snapshot", snap, nil) 94 } 95 96 //subscribeopts是订阅网络时要使用的选项集合 97 //事件 98 type SubscribeOpts struct { 99 //current指示服务器发送现有节点的事件和 100 //先连接 101 Current bool 102 103 //筛选器指示服务器仅发送消息事件的子集 104 Filter string 105 } 106 107 //订阅网络订阅从服务器发送的网络事件 108 //作为服务器发送的事件流,可以选择接收现有事件 109 //节点和连接以及筛选消息事件 110 func (c *Client) SubscribeNetwork(events chan *Event, opts SubscribeOpts) (event.Subscription, error) { 111 url := fmt.Sprintf("%s/events?current=%t&filter=%s", c.URL, opts.Current, opts.Filter) 112 req, err := http.NewRequest("GET", url, nil) 113 if err != nil { 114 return nil, err 115 } 116 req.Header.Set("Accept", "text/event-stream") 117 res, err := c.client.Do(req) 118 if err != nil { 119 return nil, err 120 } 121 if res.StatusCode != http.StatusOK { 122 response, _ := ioutil.ReadAll(res.Body) 123 res.Body.Close() 124 return nil, fmt.Errorf("unexpected HTTP status: %s: %s", res.Status, response) 125 } 126 127 //定义要传递到事件的生产者函数。订阅 128 //从Res.Body读取服务器发送的事件并发送 129 //他们到活动频道 130 producer := func(stop <-chan struct{}) error { 131 defer res.Body.Close() 132 133 //在Goroutine中阅读Res.Body的台词,这样我们 134 //总是从停止通道读取 135 lines := make(chan string) 136 errC := make(chan error, 1) 137 go func() { 138 s := bufio.NewScanner(res.Body) 139 for s.Scan() { 140 select { 141 case lines <- s.Text(): 142 case <-stop: 143 return 144 } 145 } 146 errC <- s.Err() 147 }() 148 149 //检测以“数据:”开头的任何行,解码数据 150 //将其发送到事件频道 151 for { 152 select { 153 case line := <-lines: 154 if !strings.HasPrefix(line, "data:") { 155 continue 156 } 157 data := strings.TrimSpace(strings.TrimPrefix(line, "data:")) 158 event := &Event{} 159 if err := json.Unmarshal([]byte(data), event); err != nil { 160 return fmt.Errorf("error decoding SSE event: %s", err) 161 } 162 select { 163 case events <- event: 164 case <-stop: 165 return nil 166 } 167 case err := <-errC: 168 return err 169 case <-stop: 170 return nil 171 } 172 } 173 } 174 175 return event.NewSubscription(producer), nil 176 } 177 178 //getnodes返回网络中存在的所有节点 179 func (c *Client) GetNodes() ([]*p2p.NodeInfo, error) { 180 var nodes []*p2p.NodeInfo 181 return nodes, c.Get("/nodes", &nodes) 182 } 183 184 //createNode使用给定的配置在网络中创建节点 185 func (c *Client) CreateNode(config *adapters.NodeConfig) (*p2p.NodeInfo, error) { 186 node := &p2p.NodeInfo{} 187 return node, c.Post("/nodes", config, node) 188 } 189 190 //getnode返回节点的详细信息 191 func (c *Client) GetNode(nodeID string) (*p2p.NodeInfo, error) { 192 node := &p2p.NodeInfo{} 193 return node, c.Get(fmt.Sprintf("/nodes/%s", nodeID), node) 194 } 195 196 //startnode启动节点 197 func (c *Client) StartNode(nodeID string) error { 198 return c.Post(fmt.Sprintf("/nodes/%s/start", nodeID), nil, nil) 199 } 200 201 //停止节点停止节点 202 func (c *Client) StopNode(nodeID string) error { 203 return c.Post(fmt.Sprintf("/nodes/%s/stop", nodeID), nil, nil) 204 } 205 206 //ConnectNode将节点连接到对等节点 207 func (c *Client) ConnectNode(nodeID, peerID string) error { 208 return c.Post(fmt.Sprintf("/nodes/%s/conn/%s", nodeID, peerID), nil, nil) 209 } 210 211 //断开节点断开节点与对等节点的连接 212 func (c *Client) DisconnectNode(nodeID, peerID string) error { 213 return c.Delete(fmt.Sprintf("/nodes/%s/conn/%s", nodeID, peerID)) 214 } 215 216 //rpc client返回连接到节点的rpc客户端 217 func (c *Client) RPCClient(ctx context.Context, nodeID string) (*rpc.Client, error) { 218 baseURL := strings.Replace(c.URL, "http", "ws", 1) 219 return rpc.DialWebsocket(ctx, fmt.Sprintf("%s/nodes/%s/rpc", baseURL, nodeID), "") 220 } 221 222 //GET执行HTTP GET请求,对结果JSON响应进行解码。 223 //入“出” 224 func (c *Client) Get(path string, out interface{}) error { 225 return c.Send("GET", path, nil, out) 226 } 227 228 //post执行一个HTTP post请求,将“in”作为JSON主体发送,并且 229 //将得到的JSON响应解码为“out” 230 func (c *Client) Post(path string, in, out interface{}) error { 231 return c.Send("POST", path, in, out) 232 } 233 234 //删除执行HTTP删除请求 235 func (c *Client) Delete(path string) error { 236 return c.Send("DELETE", path, nil, nil) 237 } 238 239 //send执行一个HTTP请求,将“in”作为JSON请求体发送,并且 240 //将JSON响应解码为“out” 241 func (c *Client) Send(method, path string, in, out interface{}) error { 242 var body []byte 243 if in != nil { 244 var err error 245 body, err = json.Marshal(in) 246 if err != nil { 247 return err 248 } 249 } 250 req, err := http.NewRequest(method, c.URL+path, bytes.NewReader(body)) 251 if err != nil { 252 return err 253 } 254 req.Header.Set("Content-Type", "application/json") 255 req.Header.Set("Accept", "application/json") 256 res, err := c.client.Do(req) 257 if err != nil { 258 return err 259 } 260 defer res.Body.Close() 261 if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusCreated { 262 response, _ := ioutil.ReadAll(res.Body) 263 return fmt.Errorf("unexpected HTTP status: %s: %s", res.Status, response) 264 } 265 if out != nil { 266 if err := json.NewDecoder(res.Body).Decode(out); err != nil { 267 return err 268 } 269 } 270 return nil 271 } 272 273 //服务器是一个HTTP服务器,提供用于管理模拟网络的API 274 type Server struct { 275 router *httprouter.Router 276 network *Network 277 mockerStop chan struct{} //设置后,停止当前mocker 278 mockerMtx sync.Mutex //同步访问Mockerstop字段 279 } 280 281 //NewServer返回新的模拟API服务器 282 func NewServer(network *Network) *Server { 283 s := &Server{ 284 router: httprouter.New(), 285 network: network, 286 } 287 288 s.OPTIONS("/", s.Options) 289 s.GET("/", s.GetNetwork) 290 s.POST("/start", s.StartNetwork) 291 s.POST("/stop", s.StopNetwork) 292 s.POST("/mocker/start", s.StartMocker) 293 s.POST("/mocker/stop", s.StopMocker) 294 s.GET("/mocker", s.GetMockers) 295 s.POST("/reset", s.ResetNetwork) 296 s.GET("/events", s.StreamNetworkEvents) 297 s.GET("/snapshot", s.CreateSnapshot) 298 s.POST("/snapshot", s.LoadSnapshot) 299 s.POST("/nodes", s.CreateNode) 300 s.GET("/nodes", s.GetNodes) 301 s.GET("/nodes/:nodeid", s.GetNode) 302 s.POST("/nodes/:nodeid/start", s.StartNode) 303 s.POST("/nodes/:nodeid/stop", s.StopNode) 304 s.POST("/nodes/:nodeid/conn/:peerid", s.ConnectNode) 305 s.DELETE("/nodes/:nodeid/conn/:peerid", s.DisconnectNode) 306 s.GET("/nodes/:nodeid/rpc", s.NodeRPC) 307 308 return s 309 } 310 311 //GetNetwork返回网络的详细信息 312 func (s *Server) GetNetwork(w http.ResponseWriter, req *http.Request) { 313 s.JSON(w, http.StatusOK, s.network) 314 } 315 316 //StartNetwork启动网络中的所有节点 317 func (s *Server) StartNetwork(w http.ResponseWriter, req *http.Request) { 318 if err := s.network.StartAll(); err != nil { 319 http.Error(w, err.Error(), http.StatusInternalServerError) 320 return 321 } 322 323 w.WriteHeader(http.StatusOK) 324 } 325 326 //stopNetwork停止网络中的所有节点 327 func (s *Server) StopNetwork(w http.ResponseWriter, req *http.Request) { 328 if err := s.network.StopAll(); err != nil { 329 http.Error(w, err.Error(), http.StatusInternalServerError) 330 return 331 } 332 333 w.WriteHeader(http.StatusOK) 334 } 335 336 //StartMocker启动Mocker节点模拟 337 func (s *Server) StartMocker(w http.ResponseWriter, req *http.Request) { 338 s.mockerMtx.Lock() 339 defer s.mockerMtx.Unlock() 340 if s.mockerStop != nil { 341 http.Error(w, "mocker already running", http.StatusInternalServerError) 342 return 343 } 344 mockerType := req.FormValue("mocker-type") 345 mockerFn := LookupMocker(mockerType) 346 if mockerFn == nil { 347 http.Error(w, fmt.Sprintf("unknown mocker type %q", mockerType), http.StatusBadRequest) 348 return 349 } 350 nodeCount, err := strconv.Atoi(req.FormValue("node-count")) 351 if err != nil { 352 http.Error(w, "invalid node-count provided", http.StatusBadRequest) 353 return 354 } 355 s.mockerStop = make(chan struct{}) 356 go mockerFn(s.network, s.mockerStop, nodeCount) 357 358 w.WriteHeader(http.StatusOK) 359 } 360 361 //StopMocker停止Mocker节点模拟 362 func (s *Server) StopMocker(w http.ResponseWriter, req *http.Request) { 363 s.mockerMtx.Lock() 364 defer s.mockerMtx.Unlock() 365 if s.mockerStop == nil { 366 http.Error(w, "stop channel not initialized", http.StatusInternalServerError) 367 return 368 } 369 close(s.mockerStop) 370 s.mockerStop = nil 371 372 w.WriteHeader(http.StatusOK) 373 } 374 375 //getmokerlist返回可用mocker的列表 376 func (s *Server) GetMockers(w http.ResponseWriter, req *http.Request) { 377 378 list := GetMockerList() 379 s.JSON(w, http.StatusOK, list) 380 } 381 382 //ResetNetwork将网络的所有属性重置为其初始(空)状态 383 func (s *Server) ResetNetwork(w http.ResponseWriter, req *http.Request) { 384 s.network.Reset() 385 386 w.WriteHeader(http.StatusOK) 387 } 388 389 //streamNetworkEvents将网络事件作为服务器发送的事件流进行流式处理 390 func (s *Server) StreamNetworkEvents(w http.ResponseWriter, req *http.Request) { 391 events := make(chan *Event) 392 sub := s.network.events.Subscribe(events) 393 defer sub.Unsubscribe() 394 395 //如果客户端不在,则停止流 396 var clientGone <-chan bool 397 if cn, ok := w.(http.CloseNotifier); ok { 398 clientGone = cn.CloseNotify() 399 } 400 401 //写入将给定事件和数据写入流,如下所示: 402 // 403 //事件:<事件> 404 //数据:<数据> 405 // 406 write := func(event, data string) { 407 fmt.Fprintf(w, "event: %s\n", event) 408 fmt.Fprintf(w, "data: %s\n\n", data) 409 if fw, ok := w.(http.Flusher); ok { 410 fw.Flush() 411 } 412 } 413 writeEvent := func(event *Event) error { 414 data, err := json.Marshal(event) 415 if err != nil { 416 return err 417 } 418 write("network", string(data)) 419 return nil 420 } 421 writeErr := func(err error) { 422 write("error", err.Error()) 423 } 424 425 //检查是否已请求筛选 426 var filters MsgFilters 427 if filterParam := req.URL.Query().Get("filter"); filterParam != "" { 428 var err error 429 filters, err = NewMsgFilters(filterParam) 430 if err != nil { 431 http.Error(w, err.Error(), http.StatusBadRequest) 432 return 433 } 434 } 435 436 w.Header().Set("Content-Type", "text/event-stream; charset=utf-8") 437 w.WriteHeader(http.StatusOK) 438 fmt.Fprintf(w, "\n\n") 439 if fw, ok := w.(http.Flusher); ok { 440 fw.Flush() 441 } 442 443 //可选发送现有节点和连接 444 if req.URL.Query().Get("current") == "true" { 445 snap, err := s.network.Snapshot() 446 if err != nil { 447 writeErr(err) 448 return 449 } 450 for _, node := range snap.Nodes { 451 event := NewEvent(&node.Node) 452 if err := writeEvent(event); err != nil { 453 writeErr(err) 454 return 455 } 456 } 457 for _, conn := range snap.Conns { 458 event := NewEvent(&conn) 459 if err := writeEvent(event); err != nil { 460 writeErr(err) 461 return 462 } 463 } 464 } 465 466 for { 467 select { 468 case event := <-events: 469 //仅发送与筛选器匹配的消息事件 470 if event.Msg != nil && !filters.Match(event.Msg) { 471 continue 472 } 473 if err := writeEvent(event); err != nil { 474 writeErr(err) 475 return 476 } 477 case <-clientGone: 478 return 479 } 480 } 481 } 482 483 //newmsgfilters从URL查询构造消息筛选器集合 484 //参数。 485 // 486 //该参数应为单独过滤器的虚线分隔列表, 487 //每个都具有格式“<proto>:<codes>”,其中<proto>是 488 //Protocol和<codes>是以逗号分隔的消息代码列表。 489 // 490 //“*”或“-1”的消息代码被视为通配符并与任何代码匹配。 491 func NewMsgFilters(filterParam string) (MsgFilters, error) { 492 filters := make(MsgFilters) 493 for _, filter := range strings.Split(filterParam, "-") { 494 protoCodes := strings.SplitN(filter, ":", 2) 495 if len(protoCodes) != 2 || protoCodes[0] == "" || protoCodes[1] == "" { 496 return nil, fmt.Errorf("invalid message filter: %s", filter) 497 } 498 proto := protoCodes[0] 499 for _, code := range strings.Split(protoCodes[1], ",") { 500 if code == "*" || code == "-1" { 501 filters[MsgFilter{Proto: proto, Code: -1}] = struct{}{} 502 continue 503 } 504 n, err := strconv.ParseUint(code, 10, 64) 505 if err != nil { 506 return nil, fmt.Errorf("invalid message code: %s", code) 507 } 508 filters[MsgFilter{Proto: proto, Code: int64(n)}] = struct{}{} 509 } 510 } 511 return filters, nil 512 } 513 514 //msgfilters是用于筛选消息的筛选器的集合 515 //事件 516 type MsgFilters map[MsgFilter]struct{} 517 518 //匹配检查给定消息是否与任何筛选器匹配 519 func (m MsgFilters) Match(msg *Msg) bool { 520 //检查是否存在消息协议的通配符筛选器 521 if _, ok := m[MsgFilter{Proto: msg.Protocol, Code: -1}]; ok { 522 return true 523 } 524 525 //检查是否有消息协议和代码的筛选器 526 if _, ok := m[MsgFilter{Proto: msg.Protocol, Code: int64(msg.Code)}]; ok { 527 return true 528 } 529 530 return false 531 } 532 533 //msgfilter用于根据协议和消息筛选消息事件 534 //代码 535 type MsgFilter struct { 536 //协议与消息的协议匹配 537 Proto string 538 539 //代码与消息的代码匹配,其中-1与所有代码匹配 540 Code int64 541 } 542 543 //创建快照创建网络快照 544 func (s *Server) CreateSnapshot(w http.ResponseWriter, req *http.Request) { 545 snap, err := s.network.Snapshot() 546 if err != nil { 547 http.Error(w, err.Error(), http.StatusInternalServerError) 548 return 549 } 550 551 s.JSON(w, http.StatusOK, snap) 552 } 553 554 //LoadSnapshot将快照加载到网络中 555 func (s *Server) LoadSnapshot(w http.ResponseWriter, req *http.Request) { 556 snap := &Snapshot{} 557 if err := json.NewDecoder(req.Body).Decode(snap); err != nil { 558 http.Error(w, err.Error(), http.StatusBadRequest) 559 return 560 } 561 562 if err := s.network.Load(snap); err != nil { 563 http.Error(w, err.Error(), http.StatusInternalServerError) 564 return 565 } 566 567 s.JSON(w, http.StatusOK, s.network) 568 } 569 570 //createNode使用给定的配置在网络中创建节点 571 func (s *Server) CreateNode(w http.ResponseWriter, req *http.Request) { 572 config := &adapters.NodeConfig{} 573 574 err := json.NewDecoder(req.Body).Decode(config) 575 if err != nil && err != io.EOF { 576 http.Error(w, err.Error(), http.StatusBadRequest) 577 return 578 } 579 580 node, err := s.network.NewNodeWithConfig(config) 581 if err != nil { 582 http.Error(w, err.Error(), http.StatusInternalServerError) 583 return 584 } 585 586 s.JSON(w, http.StatusCreated, node.NodeInfo()) 587 } 588 589 //getnodes返回网络中存在的所有节点 590 func (s *Server) GetNodes(w http.ResponseWriter, req *http.Request) { 591 nodes := s.network.GetNodes() 592 593 infos := make([]*p2p.NodeInfo, len(nodes)) 594 for i, node := range nodes { 595 infos[i] = node.NodeInfo() 596 } 597 598 s.JSON(w, http.StatusOK, infos) 599 } 600 601 //getnode返回节点的详细信息 602 func (s *Server) GetNode(w http.ResponseWriter, req *http.Request) { 603 node := req.Context().Value("node").(*Node) 604 605 s.JSON(w, http.StatusOK, node.NodeInfo()) 606 } 607 608 //startnode启动节点 609 func (s *Server) StartNode(w http.ResponseWriter, req *http.Request) { 610 node := req.Context().Value("node").(*Node) 611 612 if err := s.network.Start(node.ID()); err != nil { 613 http.Error(w, err.Error(), http.StatusInternalServerError) 614 return 615 } 616 617 s.JSON(w, http.StatusOK, node.NodeInfo()) 618 } 619 620 //停止节点停止节点 621 func (s *Server) StopNode(w http.ResponseWriter, req *http.Request) { 622 node := req.Context().Value("node").(*Node) 623 624 if err := s.network.Stop(node.ID()); err != nil { 625 http.Error(w, err.Error(), http.StatusInternalServerError) 626 return 627 } 628 629 s.JSON(w, http.StatusOK, node.NodeInfo()) 630 } 631 632 //ConnectNode将节点连接到对等节点 633 func (s *Server) ConnectNode(w http.ResponseWriter, req *http.Request) { 634 node := req.Context().Value("node").(*Node) 635 peer := req.Context().Value("peer").(*Node) 636 637 if err := s.network.Connect(node.ID(), peer.ID()); err != nil { 638 http.Error(w, err.Error(), http.StatusInternalServerError) 639 return 640 } 641 642 s.JSON(w, http.StatusOK, node.NodeInfo()) 643 } 644 645 //断开节点断开节点与对等节点的连接 646 func (s *Server) DisconnectNode(w http.ResponseWriter, req *http.Request) { 647 node := req.Context().Value("node").(*Node) 648 peer := req.Context().Value("peer").(*Node) 649 650 if err := s.network.Disconnect(node.ID(), peer.ID()); err != nil { 651 http.Error(w, err.Error(), http.StatusInternalServerError) 652 return 653 } 654 655 s.JSON(w, http.StatusOK, node.NodeInfo()) 656 } 657 658 //选项通过返回200 OK响应来响应选项HTTP方法 659 //将“访问控制允许邮件头”邮件头设置为“内容类型” 660 func (s *Server) Options(w http.ResponseWriter, req *http.Request) { 661 w.Header().Set("Access-Control-Allow-Headers", "Content-Type") 662 w.WriteHeader(http.StatusOK) 663 } 664 665 //node rpc通过websocket将rpc请求转发到网络中的节点 666 //连接 667 func (s *Server) NodeRPC(w http.ResponseWriter, req *http.Request) { 668 node := req.Context().Value("node").(*Node) 669 670 handler := func(conn *websocket.Conn) { 671 node.ServeRPC(conn) 672 } 673 674 websocket.Server{Handler: handler}.ServeHTTP(w, req) 675 } 676 677 //servehtp通过委托给 678 //底层httprouter.router 679 func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) { 680 s.router.ServeHTTP(w, req) 681 } 682 683 //get为特定路径的get请求注册一个处理程序 684 func (s *Server) GET(path string, handle http.HandlerFunc) { 685 s.router.GET(path, s.wrapHandler(handle)) 686 } 687 688 //post为特定路径的post请求注册一个处理程序 689 func (s *Server) POST(path string, handle http.HandlerFunc) { 690 s.router.POST(path, s.wrapHandler(handle)) 691 } 692 693 //delete为特定路径的删除请求注册处理程序 694 func (s *Server) DELETE(path string, handle http.HandlerFunc) { 695 s.router.DELETE(path, s.wrapHandler(handle)) 696 } 697 698 //选项为特定路径的选项请求注册处理程序 699 func (s *Server) OPTIONS(path string, handle http.HandlerFunc) { 700 /*outer.options(“/*路径”,s.wraphandler(handle)) 701 } 702 703 //JSON以JSON HTTP响应的形式发送“data” 704 func(s*server)json(w http.responsewriter,status int,数据接口) 705 w.header().set(“内容类型”,“应用程序/json”)。 706 w.writeheader(状态) 707 json.newencoder(w).encode(数据) 708 } 709 710 //wraphandler返回一个httprouter.handle,它将http.handlerFunc包装为 711 //用URL参数中的任何对象填充request.context 712 func(s*server)wraphandler(handlerHTTP.handlerFunc)httprouter.handle_ 713 返回func(w http.responsewriter,req*http.request,params httprouter.params) 714 w.header().set(“访问控制允许来源”,“*”) 715 w.header().set(“访问控制允许方法”、“获取、发布、放置、删除、选项”)。 716 717 ctx:=context.background()。 718 719 如果id:=params.byname(“nodeid”);id!=“{” 720 VAR节点*节点 721 如果nodeid,则错误:=discover.hexid(id);err==nil 722 node=s.network.getnode(nodeid) 723 }否则{ 724 node=s.network.getnodebyname(id) 725 } 726 如果节点==nil 727 未找到(w,req) 728 返回 729 } 730 ctx=context.withValue(ctx,“节点”,节点) 731 } 732 733 如果id:=params.byname(“peerid”);id!=“{” 734 VaR对等节点 735 如果peerID,则错误:=discover.hexid(id);err==nil 736 peer=s.network.getnode(peerid) 737 }否则{ 738 peer=s.network.getnodebyname(id) 739 } 740 如果peer==nil 741 未找到(w,req) 742 返回 743 } 744 ctx=context.withValue(ctx,“对等”,对等) 745 } 746 747 处理程序(w,req.withContext(ctx))。 748 } 749 }