func (srv *server) post(url string, jsonData []byte) (*api.Response, error) {
	var resp *http.Response
	var err error
	client := &http.Client{}
	if srv.TLSConfig != nil {
		client.Transport = srv.createTransport()
	}
	if srv.RequestTimeout != 0 {
		client.Timeout = srv.RequestTimeout
	}
	req, err := http.NewRequest("POST", url, bytes.NewReader(jsonData))
	if err != nil {
		err = fmt.Errorf("failed POST to %s: %v", url, err)
		return nil, errors.Wrap(errors.APIClientError, errors.ClientHTTPError, err)
	}
	req.Close = true
	req.Header.Set("content-type", "application/json")
	if srv.reqModifier != nil {
		srv.reqModifier(req, jsonData)
	}
	resp, err = client.Do(req)
	if err != nil {
		err = fmt.Errorf("failed POST to %s: %v", url, err)
		return nil, errors.Wrap(errors.APIClientError, errors.ClientHTTPError, err)
	}
	defer req.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, errors.Wrap(errors.APIClientError, errors.IOError, err)
	}
	if resp.StatusCode != http.StatusOK {
		log.Errorf("http error with %s", url)
		return nil, errors.Wrap(errors.APIClientError, errors.ClientHTTPError, stderr.New(string(body)))
	}
	var response api.Response
	err = json.Unmarshal(body, &response)
	if err != nil {
		log.Debug("Unable to parse response body:", string(body))
		return nil, errors.Wrap(errors.APIClientError, errors.JSONError, err)
	}
	if !response.Success || response.Result == nil {
		if len(response.Errors) > 0 {
			return nil, errors.Wrap(errors.APIClientError, errors.ServerRequestFailed, stderr.New(response.Errors[0].Message))
		}
		return nil, errors.New(errors.APIClientError, errors.ServerRequestFailed)
	}
	return &response, nil
}
post connects to the remote server and returns a Response struct
package client
import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	stderr "errors"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
	"github.com/cloudflare/cfssl/api"
	"github.com/cloudflare/cfssl/auth"
	"github.com/cloudflare/cfssl/errors"
	"github.com/cloudflare/cfssl/info"
	"github.com/cloudflare/cfssl/log"
)
type server struct {
	URL            string
	TLSConfig      *tls.Config
	reqModifier    func(*http.Request, []byte)
	RequestTimeout time.Duration
	proxy          func(*http.Request) (*url.URL, error)
}
type Remote interface {
	AuthSign(req, id []byte, provider auth.Provider) ([]byte, error)
	Sign(jsonData []byte) ([]byte, error)
	Info(jsonData []byte) (*info.Resp, error)
	Hosts() []string
	SetReqModifier(func(*http.Request, []byte))
	SetRequestTimeout(d time.Duration)
	SetProxy(func(*http.Request) (*url.URL, error))
}
func NewServer(addr string) Remote {
	return NewServerTLS(addr, nil)
}
func NewServerTLS(addr string, tlsConfig *tls.Config) Remote {
	addrs := strings.Split(addr, ",")
	var remote Remote
	if len(addrs) > 1 {
		remote, _ = NewGroup(addrs, tlsConfig, StrategyOrderedList)
	} else {
		u, err := normalizeURL(addrs[0])
		if err != nil {
			log.Errorf("bad url: %v", err)
			return nil
		}
		srv := newServer(u, tlsConfig)
		if srv != nil {
			remote = srv
		}
	}
	return remote
}
func (srv *server) Hosts() []string {
	return []string{srv.URL}
}
func (srv *server) SetReqModifier(mod func(*http.Request, []byte)) {
	srv.reqModifier = mod
}
func (srv *server) SetRequestTimeout(timeout time.Duration) {
	srv.RequestTimeout = timeout
}
func (srv *server) SetProxy(proxy func(*http.Request) (*url.URL, error)) {
	srv.proxy = proxy
}
func newServer(u *url.URL, tlsConfig *tls.Config) *server {
	URL := u.String()
	return &server{
		URL:       URL,
		TLSConfig: tlsConfig,
	}
}
func (srv *server) getURL(endpoint string) string {
	return fmt.Sprintf("%s/api/v1/cfssl/%s", srv.URL, endpoint)
}
func (srv *server) createTransport() *http.Transport {
	transport := &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		DialContext: (&net.Dialer{
			Timeout:   30 * time.Second,
			KeepAlive: 30 * time.Second,
			DualStack: true,
		}).DialContext,
		MaxIdleConns:          100,
		IdleConnTimeout:       90 * time.Second,
		TLSHandshakeTimeout:   10 * time.Second,
		ExpectContinueTimeout: 1 * time.Second,
	}
	tlsConfig := srv.TLSConfig
	tlsConfig.BuildNameToCertificate()
	transport.TLSClientConfig = tlsConfig
	if srv.proxy != nil {
		transport.Proxy = srv.proxy
	}
	return transport
}