github.com/jingruilea/kubeedge@v1.2.0-beta.0.0.20200410162146-4bb8902b3879/edge/pkg/servicebus/servicebus.go (about)

     1  package servicebus
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"net/http"
     8  	"strings"
     9  	"time"
    10  
    11  	"k8s.io/klog"
    12  
    13  	"github.com/kubeedge/beehive/pkg/core"
    14  	beehiveContext "github.com/kubeedge/beehive/pkg/core/context"
    15  	"github.com/kubeedge/beehive/pkg/core/model"
    16  	"github.com/kubeedge/kubeedge/edge/pkg/common/modules"
    17  	"github.com/kubeedge/kubeedge/edge/pkg/servicebus/util"
    18  	"github.com/kubeedge/kubeedge/pkg/apis/componentconfig/edgecore/v1alpha1"
    19  )
    20  
    21  const (
    22  	sourceType  = "router_rest"
    23  	maxBodySize = 5 * 1e6
    24  )
    25  
    26  // servicebus struct
    27  type servicebus struct {
    28  	enable bool
    29  }
    30  
    31  func newServicebus(enable bool) *servicebus {
    32  	return &servicebus{
    33  		enable: enable,
    34  	}
    35  }
    36  
    37  // Register register servicebus
    38  func Register(s *v1alpha1.ServiceBus) {
    39  	core.Register(newServicebus(s.Enable))
    40  }
    41  
    42  func (*servicebus) Name() string {
    43  	return "servicebus"
    44  }
    45  
    46  func (*servicebus) Group() string {
    47  	return modules.BusGroup
    48  }
    49  
    50  func (sb *servicebus) Enable() bool {
    51  	return sb.enable
    52  }
    53  
    54  func (sb *servicebus) Start() {
    55  	// no need to call TopicInit now, we have fixed topic
    56  	var htc = new(http.Client)
    57  	htc.Timeout = time.Second * 10
    58  
    59  	var uc = new(util.URLClient)
    60  	uc.Client = htc
    61  
    62  	//Get message from channel
    63  	for {
    64  		select {
    65  		case <-beehiveContext.Done():
    66  			klog.Warning("ServiceBus stop")
    67  			return
    68  		default:
    69  
    70  		}
    71  		msg, err := beehiveContext.Receive("servicebus")
    72  		if err != nil {
    73  			klog.Warningf("servicebus receive msg error %v", err)
    74  			continue
    75  		}
    76  		go func() {
    77  			klog.Infof("ServiceBus receive msg")
    78  			source := msg.GetSource()
    79  			if source != sourceType {
    80  				return
    81  			}
    82  			resource := msg.GetResource()
    83  			r := strings.Split(resource, ":")
    84  			if len(r) != 2 {
    85  				m := "the format of resource " + resource + " is incorrect"
    86  				klog.Warningf(m)
    87  				code := http.StatusBadRequest
    88  				if response, err := buildErrorResponse(msg.GetID(), m, code); err == nil {
    89  					beehiveContext.SendToGroup(modules.HubGroup, response)
    90  				}
    91  				return
    92  			}
    93  			content, err := json.Marshal(msg.GetContent())
    94  			if err != nil {
    95  				klog.Errorf("marshall message content failed %v", err)
    96  				m := "error to marshal request msg content"
    97  				code := http.StatusBadRequest
    98  				if response, err := buildErrorResponse(msg.GetID(), m, code); err == nil {
    99  					beehiveContext.SendToGroup(modules.HubGroup, response)
   100  				}
   101  				return
   102  			}
   103  			var httpRequest util.HTTPRequest
   104  			if err := json.Unmarshal(content, &httpRequest); err != nil {
   105  				m := "error to parse http request"
   106  				code := http.StatusBadRequest
   107  				klog.Errorf(m, err)
   108  				if response, err := buildErrorResponse(msg.GetID(), m, code); err == nil {
   109  					beehiveContext.SendToGroup(modules.HubGroup, response)
   110  				}
   111  				return
   112  			}
   113  			operation := msg.GetOperation()
   114  			targetURL := "http://127.0.0.1:" + r[0] + "/" + r[1]
   115  			resp, err := uc.HTTPDo(operation, targetURL, httpRequest.Header, httpRequest.Body)
   116  			if err != nil {
   117  				m := "error to call service"
   118  				code := http.StatusNotFound
   119  				klog.Errorf(m, err)
   120  				if response, err := buildErrorResponse(msg.GetID(), m, code); err == nil {
   121  					beehiveContext.SendToGroup(modules.HubGroup, response)
   122  				}
   123  				return
   124  			}
   125  			resp.Body = http.MaxBytesReader(nil, resp.Body, maxBodySize)
   126  			resBody, err := ioutil.ReadAll(resp.Body)
   127  			if err != nil {
   128  				if err.Error() == "http: request body too large" {
   129  					err = fmt.Errorf("response body too large")
   130  				}
   131  				m := "error to receive response, err: " + err.Error()
   132  				code := http.StatusInternalServerError
   133  				klog.Errorf(m, err)
   134  				if response, err := buildErrorResponse(msg.GetID(), m, code); err == nil {
   135  					beehiveContext.SendToGroup(modules.HubGroup, response)
   136  				}
   137  				return
   138  			}
   139  
   140  			response := util.HTTPResponse{Header: resp.Header, StatusCode: resp.StatusCode, Body: resBody}
   141  			responseMsg := model.NewMessage(msg.GetID())
   142  			responseMsg.Content = response
   143  			responseMsg.SetRoute("servicebus", modules.UserGroup)
   144  			beehiveContext.SendToGroup(modules.HubGroup, *responseMsg)
   145  		}()
   146  	}
   147  }
   148  
   149  func buildErrorResponse(parentID string, content string, statusCode int) (model.Message, error) {
   150  	responseMsg := model.NewMessage(parentID)
   151  	h := http.Header{}
   152  	h.Add("Server", "kubeedge-edgecore")
   153  	c := util.HTTPResponse{Header: h, StatusCode: statusCode, Body: []byte(content)}
   154  	responseMsg.Content = c
   155  	responseMsg.SetRoute("servicebus", modules.UserGroup)
   156  	return *responseMsg, nil
   157  }