Bug 67694505 (#29)

* Forward Proxy support made Inline.

* Forward Pxy Support

* Code review updates.

* Code review updates.
diff --git a/README.md b/README.md
index 6bf9a09..551ba2f 100644
--- a/README.md
+++ b/README.md
@@ -65,3 +65,8 @@
 This service provides the primitives to perform SQL operations on the database. It also provides the
 provision to alter DB connection pool settings via ConfigDBMaxConns, ConfigDBIdleConns and configDBConnsTimeout configuration parameters. They currently are defaulted to 1000 connections, 1000 connections and 120 seconds respectively.
 More details on this can be found at https://golang.org/pkg/database/sql
+
+
+## Making http.Client calls through Forward proxy server
+If forward proxy server related parameters are set, util.Transport() will provide the Transport roundtripper with the forward proxy parameters set.
+
diff --git a/apid.go b/apid.go
index fd325d5..97134d7 100644
--- a/apid.go
+++ b/apid.go
@@ -18,12 +18,18 @@
 	"errors"
 	"os"
 	"time"
+	"github.com/apid/apid-core/util"
 )
 
 const (
 	SystemEventsSelector  EventSelector = "system event"
 	ShutdownEventSelector EventSelector = "shutdown event"
 	ShutdownTimeout       time.Duration = 10 * time.Second
+	configfwdProxyURL	=   "configfwdproxy_url"
+	configfwdProxyProt	=   "configfwdproxy_prot"
+	configfwdProxyUser	=   "configfwdproxy_user"
+	configfwdProxyPasswd	=   "configfwdproxy_passwd"
+	configfwdProxyPort      =   "configfwdproxy_port"
 )
 
 var (
@@ -43,6 +49,23 @@
 	Log() LogService
 }
 
+func setFwdProxyConfig(config ConfigService) {
+	var pURL string
+
+	config.SetDefault(configfwdProxyProt, "https")
+	fwdPrxy := config.GetString(configfwdProxyURL)
+	fwdprxyProt := config.GetString(configfwdProxyProt)
+	fwdPrxyUser := config.GetString(configfwdProxyUser)
+	fwdPrxyPass := config.GetString(configfwdProxyPasswd)
+	fwdPrxyPort := config.GetString(configfwdProxyPort)
+	if fwdPrxy != "" && fwdPrxyUser != "" && fwdPrxyPort != "" {
+		pURL = fwdprxyProt + "://" + fwdPrxyUser + ":" + fwdPrxyPass + "@" + fwdPrxy + ":" + fwdPrxyPort
+	} else if fwdPrxy != "" && fwdPrxyPort != "" {
+		pURL = fwdprxyProt + "://" + fwdPrxy + ":" + fwdPrxyPort
+	}
+	config.Set(util.ConfigfwdProxyPortURL, pURL)
+}
+
 type PluginInitFunc func(Services) (PluginData, error)
 
 // passed Services can be a factory - makes copies and maintains returned references
@@ -60,7 +83,7 @@
 	if err := os.MkdirAll(lsp, 0700); err != nil {
 		ss.log.Panicf("can't create local storage path %s: %v", lsp, err)
 	}
-
+	setFwdProxyConfig(ss.config)
 	ss.events = s.Events()
 	ss.api = s.API()
 	ss.data = s.Data()
diff --git a/util/util.go b/util/util.go
index ad936ff..4178030 100644
--- a/util/util.go
+++ b/util/util.go
@@ -14,11 +14,14 @@
 
 package util
 
+
 import (
 	"github.com/google/uuid"
 	"net/http"
+	"net/url"
 	"time"
 )
+const ConfigfwdProxyPortURL   =   "configcompletefwdp"
 
 func IsValidUUID(id string) bool {
 	_, err := uuid.Parse(id)
@@ -29,6 +32,21 @@
 	return uuid.New().String()
 }
 
+// Helper method that initializes the roundtripper based on the configuration parameters.
+func Transport(pURL string) *http.Transport {
+	var tr http.Transport
+	if pURL != "" {
+		paURL, err := url.Parse(pURL)
+		if err != nil {
+			panic("Error parsing proxy URL")
+		}
+		tr = http.Transport{
+			Proxy:           http.ProxyURL(paURL),
+		}
+	}
+	return &tr
+}
+
 // distributeEvents() receives elements from deliverChan, and send them to subscribers
 // Sending a `chan interface{}` to addSubscriber adds a new subscriber.
 // It closes the subscriber channel after sending the element.
diff --git a/util/util_test.go b/util/util_test.go
index 54fd997..b6c1093 100644
--- a/util/util_test.go
+++ b/util/util_test.go
@@ -18,6 +18,8 @@
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
 
+
+	"net/http/httptest"
 	"github.com/apid/apid-core/util"
 	"math/rand"
 	"net/http"
@@ -61,6 +63,47 @@
 		})
 	})
 
+	Context("Forward Proxy Protocol", func() {
+		It("Verify Forward proxying to server works", func() {
+			var maxIdleConnsPerHost = 10
+			var tr *http.Transport
+			server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+				Fail("Cant come here, as we have not forwarded request from fwdPrxyServer")
+			}))
+			fwdPrxyServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+				Expect(r.Header.Get("foo")).Should(Equal("bar"))
+				w.Header().Set("bar", "foo")
+			}))
+			tr = util.Transport(fwdPrxyServer.URL)
+			tr.MaxIdleConnsPerHost =  maxIdleConnsPerHost
+			var rspcnt int = 0
+			ch := make(chan *http.Response)
+			client := &http.Client{Transport: tr}
+			for i := 0; i < 2*maxIdleConnsPerHost; i++ {
+				go func(client *http.Client) {
+					defer GinkgoRecover()
+					req, err := http.NewRequest("GET", server.URL, nil)
+					Expect(err).Should(Succeed())
+					req.Header.Set("foo", "bar")
+					resp, err := client.Do(req)
+					Expect(err).Should(Succeed())
+					Expect(resp.Header.Get("bar")).Should(Equal("foo"))
+					resp.Body.Close()
+					ch <- resp
+				}(client)
+			}
+			for {
+				resp := <-ch
+				Expect(resp.StatusCode).To(Equal(http.StatusOK))
+				if rspcnt >= 2*maxIdleConnsPerHost-1 {
+					return
+				}
+				rspcnt++
+			}
+
+		}, 3)
+	})
+
 	Context("Long polling utils", func() {
 		It("DistributeEvents", func() {
 			// make test data