Beispiel #1
0
func (s *RpcServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	serveCtx := getServerContext(req)

	// TODO: get user scope from context
	// check access

	if req.Method != "POST" {
		err := errors.BadRequest("go.micro.server", "Method not allowed")
		http.Error(w, err.Error(), http.StatusMethodNotAllowed)
		return
	}
	defer req.Body.Close()

	b, err := ioutil.ReadAll(req.Body)
	if err != nil {
		errr := errors.InternalServerError("go.micro.server", fmt.Sprintf("Error reading request body: %v", err))
		w.WriteHeader(500)
		w.Write([]byte(errr.Error()))
		log.Errorf("Erroring reading request body: %v", err)
		return
	}

	rbq := bytes.NewBuffer(b)
	rsp := bytes.NewBuffer(nil)
	defer rsp.Reset()
	defer rbq.Reset()

	buf := &buffer{
		rbq,
		rsp,
	}

	var cc rpc.ServerCodec
	switch req.Header.Get("Content-Type") {
	case "application/octet-stream":
		cc = pb.NewServerCodec(buf)
	case "application/json":
		cc = js.NewServerCodec(buf)
	default:
		err = errors.InternalServerError("go.micro.server", fmt.Sprintf("Unsupported content-type: %v", req.Header.Get("Content-Type")))
		w.WriteHeader(500)
		w.Write([]byte(err.Error()))
		return
	}

	ctx := newContext(&ctx{}, serveCtx)
	err = s.rpc.ServeRequestWithContext(ctx, cc)
	if err != nil {
		// This should not be possible.
		w.WriteHeader(500)
		w.Write([]byte(err.Error()))
		log.Errorf("Erroring serving request: %v", err)
		return
	}

	w.Header().Set("Content-Type", req.Header.Get("Content-Type"))
	w.Header().Set("Content-Length", strconv.Itoa(rsp.Len()))
	w.Write(rsp.Bytes())
}
Beispiel #2
0
func executeRequestSafely(c *serverContext, r *http.Request) {
	defer func() {
		if x := recover(); x != nil {
			log.Warningf("Panicked on request: %v", r)
			log.Warningf("%v: %v", x, string(debug.Stack()))
			err := errors.InternalServerError("go.micro.server", "Unexpected error")
			c.WriteHeader(500)
			c.Write([]byte(err.Error()))
		}
	}()

	http.DefaultServeMux.ServeHTTP(c, r)
}
Beispiel #3
0
// TODO: Call(..., opts *Options) error {
func (r *RpcClient) Call(request Request, response interface{}) error {
	service, err := registry.GetService(request.Service())
	if err != nil {
		return errors.InternalServerError("go.micro.client", err.Error())
	}

	if len(service.Nodes()) == 0 {
		return errors.NotFound("go.micro.client", "Service not found")
	}

	n := rand.Int() % len(service.Nodes())
	node := service.Nodes()[n]
	address := fmt.Sprintf("%s:%d", node.Address(), node.Port())
	return r.call(address, "/_rpc", request, response)
}
Beispiel #4
0
func (r *RpcClient) call(address, path string, request Request, response interface{}) error {
	pReq := &rpc.Request{
		ServiceMethod: request.Method(),
	}

	reqB := bytes.NewBuffer(nil)
	defer reqB.Reset()
	buf := &buffer{
		reqB,
	}

	var cc rpc.ClientCodec
	switch request.ContentType() {
	case "application/octet-stream":
		cc = pb.NewClientCodec(buf)
	case "application/json":
		cc = js.NewClientCodec(buf)
	default:
		return errors.InternalServerError("go.micro.client", fmt.Sprintf("Unsupported request type: %s", request.ContentType()))
	}

	err := cc.WriteRequest(pReq, request.Request())
	if err != nil {
		return errors.InternalServerError("go.micro.client", fmt.Sprintf("Error writing request: %v", err))
	}

	client := &http.Client{}
	client.Transport = &headerRoundTripper{http.DefaultTransport}

	request.Headers().Set("Content-Type", request.ContentType())

	hreq := &http.Request{
		Method: "POST",
		URL: &url.URL{
			Scheme: "http",
			Host:   address,
			Path:   path,
		},
		Header:        request.Headers().(http.Header),
		Body:          buf,
		ContentLength: int64(reqB.Len()),
		Host:          address,
	}

	rsp, err := client.Do(hreq)
	if err != nil {
		return errors.InternalServerError("go.micro.client", fmt.Sprintf("Error sending request: %v", err))
	}
	defer rsp.Body.Close()

	b, err := ioutil.ReadAll(rsp.Body)
	if err != nil {
		return errors.InternalServerError("go.micro.client", fmt.Sprintf("Error reading response: %v", err))
	}

	rspB := bytes.NewBuffer(b)
	defer rspB.Reset()
	rBuf := &buffer{
		rspB,
	}

	switch rsp.Header.Get("Content-Type") {
	case "application/octet-stream":
		cc = pb.NewClientCodec(rBuf)
	case "application/json":
		cc = js.NewClientCodec(rBuf)
	default:
		return errors.InternalServerError("go.micro.client", string(b))
	}

	pRsp := &rpc.Response{}
	err = cc.ReadResponseHeader(pRsp)
	if err != nil {
		return errors.InternalServerError("go.micro.client", fmt.Sprintf("Error reading response headers: %v", err))
	}

	if len(pRsp.Error) > 0 {
		return errors.Parse(pRsp.Error)
	}

	err = cc.ReadResponseBody(response)
	if err != nil {
		return errors.InternalServerError("go.micro.client", fmt.Sprintf("Error reading response body: %v", err))
	}

	return nil
}