github.com/prebid/prebid-server/v2@v2.18.0/stored_requests/events/api/api.go (about)

     1  package api
     2  
     3  import (
     4  	"io"
     5  	"net/http"
     6  
     7  	"github.com/julienschmidt/httprouter"
     8  	"github.com/prebid/prebid-server/v2/stored_requests/events"
     9  	"github.com/prebid/prebid-server/v2/util/jsonutil"
    10  )
    11  
    12  type eventsAPI struct {
    13  	saves         chan events.Save
    14  	invalidations chan events.Invalidation
    15  }
    16  
    17  // NewEventsAPI creates an EventProducer that generates cache events from HTTP requests.
    18  // The returned httprouter.Handle must be registered on both POST (update) and DELETE (invalidate)
    19  // methods and provided an `:id` param via the URL, e.g.:
    20  //
    21  // apiEvents, apiEventsHandler, err := NewEventsApi()
    22  // router.POST("/stored_requests", apiEventsHandler)
    23  // router.DELETE("/stored_requests", apiEventsHandler)
    24  // listener := events.Listen(cache, apiEvents)
    25  //
    26  // The returned HTTP endpoint should not be exposed on a public network without authentication
    27  // as it allows direct writing to the cache via Update.
    28  func NewEventsAPI() (events.EventProducer, httprouter.Handle) {
    29  	api := &eventsAPI{
    30  		invalidations: make(chan events.Invalidation),
    31  		saves:         make(chan events.Save),
    32  	}
    33  	return api, httprouter.Handle(api.HandleEvent)
    34  }
    35  
    36  func (api *eventsAPI) HandleEvent(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
    37  	if r.Method == "POST" {
    38  		body, err := io.ReadAll(r.Body)
    39  		if err != nil {
    40  			w.WriteHeader(http.StatusBadRequest)
    41  			w.Write([]byte("Missing update data.\n"))
    42  			return
    43  		}
    44  
    45  		var save events.Save
    46  		if err := jsonutil.UnmarshalValid(body, &save); err != nil {
    47  			w.WriteHeader(http.StatusBadRequest)
    48  			w.Write([]byte("Invalid update.\n"))
    49  			return
    50  		}
    51  
    52  		api.saves <- save
    53  	} else if r.Method == "DELETE" {
    54  		body, err := io.ReadAll(r.Body)
    55  		if err != nil {
    56  			w.WriteHeader(http.StatusBadRequest)
    57  			w.Write([]byte("Missing invalidation data.\n"))
    58  			return
    59  		}
    60  
    61  		var invalidation events.Invalidation
    62  		if err := jsonutil.UnmarshalValid(body, &invalidation); err != nil {
    63  			w.WriteHeader(http.StatusBadRequest)
    64  			w.Write([]byte("Invalid invalidation.\n"))
    65  			return
    66  		}
    67  
    68  		api.invalidations <- invalidation
    69  	} else {
    70  		w.WriteHeader(http.StatusMethodNotAllowed)
    71  	}
    72  }
    73  
    74  func (api *eventsAPI) Invalidations() <-chan events.Invalidation {
    75  	return api.invalidations
    76  }
    77  
    78  func (api *eventsAPI) Saves() <-chan events.Save {
    79  	return api.saves
    80  }