github.com/Financial-Times/publish-availability-monitor@v1.12.0/content/content.go (about)

     1  package content
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  	"net/http"
     7  
     8  	"github.com/Financial-Times/go-logger/v2"
     9  	"github.com/Financial-Times/publish-availability-monitor/httpcaller"
    10  )
    11  
    12  // Content is the interface for different type of contents from different CMSs.
    13  type Content interface {
    14  	Initialize(binaryContent []byte) Content
    15  	Validate(externalValidationEndpoint, tid, username, password string, log *logger.UPPLogger) ValidationResponse
    16  	GetType() string
    17  	GetUUID() string
    18  }
    19  
    20  type ValidationResponse struct {
    21  	IsValid         bool
    22  	IsMarkedDeleted bool
    23  }
    24  
    25  type validationParam struct {
    26  	binaryContent    []byte
    27  	validationURL    string
    28  	username         string
    29  	password         string
    30  	tid              string
    31  	uuid             string
    32  	contentType      string
    33  	isGenericPublish bool
    34  }
    35  
    36  var httpCaller httpcaller.Caller
    37  
    38  func init() {
    39  	httpCaller = httpcaller.NewCaller(10)
    40  }
    41  
    42  func doExternalValidation(p validationParam, validCheck func(int) bool, deletedCheck func(...int) bool, log *logger.UPPLogger) ValidationResponse {
    43  	logEntry := log.WithUUID(p.uuid).WithTransactionID(p.tid)
    44  
    45  	if p.validationURL == "" {
    46  		logEntry.Warnf("External validation for content. Validation endpoint URL is missing for content type=[%s]", p.contentType)
    47  		return ValidationResponse{false, deletedCheck()}
    48  	}
    49  
    50  	logEntry = logEntry.WithField("validation_url", p.validationURL)
    51  
    52  	contentType := "application/json"
    53  	if p.isGenericPublish {
    54  		contentType = p.contentType
    55  	}
    56  
    57  	resp, err := httpCaller.DoCall(httpcaller.Config{
    58  		HTTPMethod:  "POST",
    59  		URL:         p.validationURL,
    60  		Username:    p.username,
    61  		Password:    p.password,
    62  		TID:         httpcaller.ConstructPamTID(p.tid),
    63  		ContentType: contentType,
    64  		Entity:      bytes.NewReader(p.binaryContent),
    65  	})
    66  
    67  	if err != nil {
    68  		logEntry.WithError(err).Warn("External validation for content failed while creating validation request. Skipping external validation.")
    69  		return ValidationResponse{true, deletedCheck()}
    70  	}
    71  	defer resp.Body.Close()
    72  
    73  	logEntry.Infof("External validation received statusCode [%d]", resp.StatusCode)
    74  
    75  	bs, err := io.ReadAll(resp.Body)
    76  	if err != nil {
    77  		logEntry.WithError(err).Warn("External validation reading response body error")
    78  	}
    79  
    80  	if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusNotFound {
    81  		logEntry.Infof("External validation received statusCode [%d], received error: [%v]", resp.StatusCode, string(bs))
    82  	}
    83  
    84  	if resp.StatusCode == http.StatusNotFound {
    85  		logEntry.Infof("External validation received statusCode [%d], content is marked as deleted.", resp.StatusCode)
    86  	}
    87  
    88  	return ValidationResponse{validCheck(resp.StatusCode), deletedCheck(resp.StatusCode)}
    89  }