proxy/protocol/grpc/client.go (98 lines of code) (raw):

/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package grpc import ( "context" "crypto/tls" "errors" "net" "net/http" "github.com/go-chassis/go-chassis/v2/core/client" "github.com/go-chassis/go-chassis/v2/core/invocation" "github.com/go-chassis/go-chassis/v2/pkg/util/httputil" "golang.org/x/net/http2" ) const ( //SchemaHTTP represents the http schema SchemaHTTP = "http" //SchemaHTTPS represents the https schema SchemaHTTPS = "https" ) //ErrInvalidResp invalid input var ( ErrInvalidResp = errors.New("rest consumer response arg is not *http.Response type") //ErrCanceled means Request is canceled by context management ErrCanceled = errors.New("request cancelled") ) //Client is a grpc client type Client struct { c *http.Client opts client.Options } var protocolName = "grpc" func init() { client.InstallPlugin(protocolName, NewClient) } //NewClient return a new client of grpc func NewClient(opts client.Options) (client.ProtocolClient, error) { client := &http.Client{} if opts.TLSConfig != nil { client.Transport = &http2.Transport{ TLSClientConfig: opts.TLSConfig, } } else { client.Transport = &http2.Transport{ AllowHTTP: true, DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) { return net.Dial(network, addr) }} } return &Client{ c: client, opts: opts, }, nil } // if your protocol has response status(such as http return 200, 500 status code), // you need to return it according to response func (c *Client) Status(rsp interface{}) (status int, err error) { return 0, nil } //Call is a method which uses grpc protocol to transfer invocation func (c *Client) Call(ctx context.Context, addr string, inv *invocation.Invocation, rsp interface{}) error { var err error reqSend, err := httputil.HTTPRequest(inv) if err != nil { return err } resp, ok := rsp.(*http.Response) if !ok { return ErrInvalidResp } ctx, cancel := context.WithCancel(ctx) defer cancel() if c.opts.TLSConfig != nil { reqSend.URL.Scheme = SchemaHTTPS } else { reqSend.URL.Scheme = SchemaHTTP } if addr != "" { reqSend.URL.Host = addr } var temp *http.Response errChan := make(chan error, 1) go func() { temp, err = c.c.Do(reqSend) errChan <- err }() select { case <-ctx.Done(): err = ErrCanceled case err = <-errChan: if err == nil { *resp = *temp } } return err } //String return name func (c *Client) String() string { return protocolName } //Close close the conn func (c *Client) Close() error { return nil } // ReloadConfigs reload config func (c *Client) ReloadConfigs(opts client.Options) { c.opts = client.EqualOpts(c.opts, opts) c.c.Timeout = opts.Timeout } // GetOptions return opts func (c *Client) GetOptions() client.Options { return c.opts }