github.com/jaylevin/jenkins-library@v1.230.4/pkg/sonar/client.go (about)

     1  package sonar
     2  
     3  import (
     4  	"encoding/json"
     5  	"net/http"
     6  	"strings"
     7  
     8  	"github.com/SAP/jenkins-library/pkg/log"
     9  	sonargo "github.com/magicsong/sonargo/sonar"
    10  )
    11  
    12  // Requester ...
    13  type Requester struct {
    14  	Client   Sender
    15  	Host     string
    16  	Username string
    17  	Password string
    18  	// TODO: implement certificate handling
    19  	// Certificates [][]byte
    20  }
    21  
    22  // Sender provides an interface to the piper http client for uid/pwd and token authenticated requests
    23  type Sender interface {
    24  	Send(*http.Request) (*http.Response, error)
    25  }
    26  
    27  func (requester *Requester) create(method, path string, options interface{}) (request *http.Request, err error) {
    28  	sonarGoClient, err := sonargo.NewClient(requester.Host, requester.Username, requester.Password)
    29  	if err != nil {
    30  		return
    31  	}
    32  	// reuse request creation from sonargo
    33  	request, err = sonarGoClient.NewRequest(method, path, options)
    34  	if err != nil {
    35  		return
    36  	}
    37  	// request created by sonarGO uses .Opaque without the host parameter leading to a request against https://api/issues/search
    38  	// https://github.com/magicsong/sonargo/blob/103eda7abc20bd192a064b6eb94ba26329e339f1/sonar/sonarqube.go#L55
    39  	request.URL.Opaque = ""
    40  	request.URL.Path = sonarGoClient.BaseURL().Path + path
    41  	return
    42  }
    43  
    44  func (requester *Requester) send(request *http.Request) (*http.Response, error) {
    45  	return requester.Client.Send(request)
    46  }
    47  
    48  func (requester *Requester) decode(response *http.Response, result interface{}) error {
    49  	decoder := json.NewDecoder(response.Body)
    50  	defer response.Body.Close()
    51  	// sonargo.IssuesSearchObject does not imlement "internal" field organization and thus decoding fails
    52  	// anyway the field is currently not needed so we simply allow (and drop) unknown fields to avoid extending the type
    53  	// decoder.DisallowUnknownFields()
    54  	return decoder.Decode(result)
    55  }
    56  
    57  // NewAPIClient ...
    58  func NewAPIClient(host, token string, client Sender) *Requester {
    59  	// Make sure the given URL end with a slash
    60  	if !strings.HasSuffix(host, "/") {
    61  		host += "/"
    62  	}
    63  	// Make sure the given URL end with a api/
    64  	if !strings.HasSuffix(host, "api/") {
    65  		host += "api/"
    66  	}
    67  	log.Entry().Debugf("using api client for '%s'", host)
    68  	return &Requester{
    69  		Client:   client,
    70  		Host:     host,
    71  		Username: token,
    72  	}
    73  }