func (c *Client) newDelete(endpoint string) (*http.Request, error) {
	curl, err := c.getURL(endpoint)
	if err != nil {
		return nil, err
	}
	req, err := http.NewRequest("DELETE", curl, bytes.NewReader([]byte{}))
	if err != nil {
		return nil, errors.Wrapf(err, "Failed creating DELETE request for %s", curl)
	}
	return req, nil
}
newDelete create a new DELETE request
package lib
import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"strconv"
	"strings"
	"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core"
	cfsslapi "github.com/cloudflare/cfssl/api"
	"github.com/cloudflare/cfssl/csr"
	"github.com/kfsoftware/hlf-operator/internal/github.com/hyperledger/fabric-ca/lib/client/credential"
	x509cred "github.com/kfsoftware/hlf-operator/internal/github.com/hyperledger/fabric-ca/lib/client/credential/x509"
	"github.com/kfsoftware/hlf-operator/internal/github.com/hyperledger/fabric-ca/lib/streamer"
	"github.com/kfsoftware/hlf-operator/internal/github.com/hyperledger/fabric-ca/lib/tls"
	"github.com/kfsoftware/hlf-operator/internal/github.com/hyperledger/fabric-ca/sdkinternal/pkg/api"
	"github.com/kfsoftware/hlf-operator/internal/github.com/hyperledger/fabric-ca/sdkinternal/pkg/util"
	log "github.com/kfsoftware/hlf-operator/internal/github.com/hyperledger/fabric-ca/sdkpatch/logbridge"
	"github.com/mitchellh/mapstructure"
	"github.com/pkg/errors"
)
type Client struct {
	HomeDir string `json:"homeDir,omitempty"`
	Config *ClientConfig
	initialized bool
	keyFile, certFile, idemixCredFile, idemixCredsDir, ipkFile, caCertsDir string
	csp core.CryptoSuite
	httpClient *http.Client
}
type GetCAInfoResponse struct {
	CAName string
	CAChain []byte
	IssuerPublicKey []byte
	IssuerRevocationPublicKey []byte
	Version string
}
type EnrollmentResponse struct {
	Identity *Identity
	CAInfo   GetCAInfoResponse
}
func (c *Client) Init() error {
	if !c.initialized {
		cfg := c.Config
		log.Debugf("Initializing client with config: %+v", cfg)
		if cfg.MSPDir == "" {
			cfg.MSPDir = "msp"
		}
		mspDir, err := util.MakeFileAbs(cfg.MSPDir, c.HomeDir)
		if err != nil {
			return err
		}
		cfg.MSPDir = mspDir
		keyDir := path.Join(mspDir, "keystore")
		err = os.MkdirAll(keyDir, 0700)
		if err != nil {
			return errors.Wrap(err, "Failed to create keystore directory")
		}
		c.keyFile = path.Join(keyDir, "key.pem")
		certDir := path.Join(mspDir, "signcerts")
		err = os.MkdirAll(certDir, 0755)
		if err != nil {
			return errors.Wrap(err, "Failed to create signcerts directory")
		}
		c.certFile = path.Join(certDir, "cert.pem")
		c.caCertsDir = path.Join(mspDir, "cacerts")
		err = os.MkdirAll(c.caCertsDir, 0755)
		if err != nil {
			return errors.Wrap(err, "Failed to create cacerts directory")
		}
		c.ipkFile = filepath.Join(mspDir, "IssuerPublicKey")
		c.idemixCredsDir = path.Join(mspDir, "user")
		err = os.MkdirAll(c.idemixCredsDir, 0755)
		if err != nil {
			return errors.Wrap(err, "Failed to create Idemix credentials directory 'user'")
		}
		c.idemixCredFile = path.Join(c.idemixCredsDir, "SignerConfig")
		c.csp = cfg.CSP
		err = c.initHTTPClient(cfg.ServerName)
		if err != nil {
			return err
		}
		c.initialized = true
	}
	return nil
}
func (c *Client) initHTTPClient(serverName string) error {
	tr := new(http.Transport)
	if c.Config.TLS.Enabled {
		log.Info("TLS Enabled")
		tlsConfig, err2 := tls.GetClientTLSConfig(&c.Config.TLS, c.csp)
		if err2 != nil {
			return fmt.Errorf("Failed to get client TLS config: %s", err2)
		}
		tlsConfig.CipherSuites = tls.DefaultCipherSuites
		tlsConfig.ServerName = serverName
		tr.TLSClientConfig = tlsConfig
	}
	c.httpClient = &http.Client{Transport: tr}
	return nil
}
func (c *Client) GetCAInfo(req *api.GetCAInfoRequest) (*GetCAInfoResponse, error) {
	err := c.Init()
	if err != nil {
		return nil, err
	}
	body, err := util.Marshal(req, "GetCAInfo")
	if err != nil {
		return nil, err
	}
	cainforeq, err := c.newPost("cainfo", body)
	if err != nil {
		return nil, err
	}
	netSI := &api.CAInfoResponseNet{}
	err = c.SendReq(cainforeq, netSI)
	if err != nil {
		return nil, err
	}
	localSI := &GetCAInfoResponse{}
	err = c.net2LocalCAInfo(netSI, localSI)
	if err != nil {
		return nil, err
	}
	return localSI, nil
}
func (c *Client) GenCSR(req *api.CSRInfo, id string) ([]byte, core.Key, error) {
	log.Debugf("GenCSR %+v", req)
	err := c.Init()
	if err != nil {
		return nil, nil, err
	}
	cr := c.newCertificateRequest(req)
	cr.CN = id
	if (cr.KeyRequest == nil) || (cr.KeyRequest.Size() == 0 && cr.KeyRequest.Algo() == "") {
		cr.KeyRequest = newCfsslKeyRequest(api.NewKeyRequest())
	}
	key, cspSigner, err := util.BCCSPKeyRequestGenerate(cr, c.csp)
	if err != nil {
		log.Debugf("failed generating BCCSP key: %s", err)
		return nil, nil, err
	}
	csrPEM, err := csr.Generate(cspSigner, cr)
	if err != nil {
		log.Debugf("failed generating CSR: %s", err)
		return nil, nil, err
	}
	return csrPEM, key, nil
}
func (c *Client) Enroll(req *api.EnrollmentRequest) (*EnrollmentResponse, error) {
	log.Debugf("Enrolling %+v", req)
	err := c.Init()
	if err != nil {
		return nil, err
	}
	if strings.ToLower(req.Type) == "idemix" {
		return c.handleIdemixEnroll(req)
	}
	return c.handleX509Enroll(req)
}
func (c *Client) net2LocalCAInfo(net *api.CAInfoResponseNet, local *GetCAInfoResponse) error {
	caChain, err := util.B64Decode(net.CAChain)
	if err != nil {
		return errors.WithMessage(err, "Failed to decode CA chain")
	}
	if net.IssuerPublicKey != "" {
		ipk, err := util.B64Decode(net.IssuerPublicKey)
		if err != nil {
			return errors.WithMessage(err, "Failed to decode issuer public key")
		}
		local.IssuerPublicKey = ipk
	}
	if net.IssuerRevocationPublicKey != "" {
		rpk, err := util.B64Decode(net.IssuerRevocationPublicKey)
		if err != nil {
			return errors.WithMessage(err, "Failed to decode issuer revocation key")
		}
		local.IssuerRevocationPublicKey = rpk
	}
	local.CAName = net.CAName
	local.CAChain = caChain
	local.Version = net.Version
	return nil
}
func (c *Client) handleX509Enroll(req *api.EnrollmentRequest) (*EnrollmentResponse, error) {
	csrPEM, key, err := c.GenCSR(req.CSR, req.Name)
	if err != nil {
		return nil, errors.WithMessage(err, "Failure generating CSR")
	}
	reqNet := &api.EnrollmentRequestNet{
		CAName:   req.CAName,
		AttrReqs: req.AttrReqs,
	}
	if req.CSR != nil {
		reqNet.SignRequest.Hosts = req.CSR.Hosts
	}
	reqNet.SignRequest.Request = string(csrPEM)
	reqNet.SignRequest.Profile = req.Profile
	reqNet.SignRequest.Label = req.Label
	body, err := util.Marshal(reqNet, "SignRequest")
	if err != nil {
		return nil, err
	}
	post, err := c.newPost("enroll", body)
	if err != nil {
		return nil, err
	}
	post.SetBasicAuth(req.Name, req.Secret)
	var result api.EnrollmentResponseNet
	err = c.SendReq(post, &result)
	if err != nil {
		return nil, err
	}
	return c.newEnrollmentResponse(&result, req.Name, key)
}
func (c *Client) handleIdemixEnroll(req *api.EnrollmentRequest) (*EnrollmentResponse, error) {
	log.Infof("Successfully received Idemix credential from CA %s", req.CAName)
	return nil, errors.New("idemix enroll not supported")
}
func (c *Client) newEnrollmentResponse(result *api.EnrollmentResponseNet, id string, key core.Key) (*EnrollmentResponse, error) {
	log.Debugf("newEnrollmentResponse %s", id)
	certByte, err := util.B64Decode(result.Cert)
	if err != nil {
		return nil, errors.WithMessage(err, "Invalid response format from server")
	}
	signer, err := x509cred.NewSigner(key, certByte)
	if err != nil {
		return nil, err
	}
	x509Cred := x509cred.NewCredential(key, certByte, c)
	err = x509Cred.SetVal(signer)
	if err != nil {
		return nil, err
	}
	resp := &EnrollmentResponse{
		Identity: NewIdentity(c, id, []credential.Credential{x509Cred}),
	}
	err = c.net2LocalCAInfo(&result.ServerInfo, &resp.CAInfo)
	if err != nil {
		return nil, err
	}
	return resp, nil
}
func (c *Client) newCertificateRequest(req *api.CSRInfo) *csr.CertificateRequest {
	cr := csr.CertificateRequest{}
	if req != nil && req.Names != nil {
		cr.Names = req.Names
	}
	if req != nil && req.Hosts != nil {
		cr.Hosts = req.Hosts
	} else {
		hostname, _ := os.Hostname()
		if hostname != "" {
			cr.Hosts = make([]string, 1)
			cr.Hosts[0] = hostname
		}
	}
	if req != nil && req.KeyRequest != nil {
		cr.KeyRequest = newCfsslKeyRequest(req.KeyRequest)
	}
	if req != nil {
		cr.CA = req.CA
		cr.SerialNumber = req.SerialNumber
	}
	return &cr
}
func (c *Client) NewIdentity(creds []credential.Credential) (*Identity, error) {
	if len(creds) == 0 {
		return nil, errors.New("No credentials spcified. Atleast one credential must be specified")
	}
	name, err := creds[0].EnrollmentID()
	if err != nil {
		return nil, err
	}
	if len(creds) == 1 {
		return NewIdentity(c, name, creds), nil
	}
	return NewIdentity(c, name, creds), nil
}
func (c *Client) NewX509Identity(name string, creds []credential.Credential) x509cred.Identity {
	return NewIdentity(c, name, creds)
}
func (c *Client) GetCSP() core.CryptoSuite {
	return c.csp
}
func (c *Client) newGet(endpoint string) (*http.Request, error) {
	curl, err := c.getURL(endpoint)
	if err != nil {
		return nil, err
	}
	req, err := http.NewRequest("GET", curl, bytes.NewReader([]byte{}))
	if err != nil {
		return nil, errors.Wrapf(err, "Failed creating GET request for %s", curl)
	}
	return req, nil
}
func (c *Client) newPut(endpoint string, reqBody []byte) (*http.Request, error) {
	curl, err := c.getURL(endpoint)
	if err != nil {
		return nil, err
	}
	req, err := http.NewRequest("PUT", curl, bytes.NewReader(reqBody))
	if err != nil {
		return nil, errors.Wrapf(err, "Failed creating PUT request for %s", curl)
	}
	return req, nil
}