github.com/web-platform-tests/wpt.fyi@v0.0.0-20240530210107-70cf978996f1/api/bsf_handler.go (about)

     1  // Copyright 2020 The WPT Dashboard Project. All rights reserved.
     2  // Use of this source code is governed by a BSD-style license that can be
     3  // found in the LICENSE file.
     4  
     5  package api
     6  
     7  import (
     8  	"encoding/json"
     9  	"net/http"
    10  	"time"
    11  
    12  	"github.com/web-platform-tests/wpt.fyi/shared"
    13  )
    14  
    15  // BSFHandler is an http.Handler for the /api/bsf endpoint.
    16  type BSFHandler struct {
    17  	fetcher shared.FetchBSF
    18  }
    19  
    20  // apiBSFHandler fetches browser-specific failure data based on the URL params.
    21  func apiBSFHandler(w http.ResponseWriter, r *http.Request) {
    22  	ctx := r.Context()
    23  	// Serve cached with 60-minute expiry. Delegate to BSFHandler on cache miss.
    24  	shared.NewCachingHandler(
    25  		ctx,
    26  		BSFHandler{shared.NewFetchBSF()},
    27  		shared.NewGZReadWritable(shared.NewRedisReadWritable(ctx, 60*time.Minute)),
    28  		shared.AlwaysCachable,
    29  		shared.URLAsCacheKey,
    30  		shared.CacheStatusOK).ServeHTTP(w, r)
    31  }
    32  
    33  func (b BSFHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    34  	var err error
    35  	q := r.URL.Query()
    36  
    37  	var from *time.Time
    38  	if from, err = shared.ParseDateTimeParam(q, "from"); err != nil {
    39  		http.Error(w, err.Error(), http.StatusBadRequest)
    40  
    41  		return
    42  	}
    43  
    44  	var to *time.Time
    45  	if to, err = shared.ParseDateTimeParam(q, "to"); err != nil {
    46  		http.Error(w, err.Error(), http.StatusBadRequest)
    47  
    48  		return
    49  	}
    50  
    51  	isExperimental := false
    52  	val, _ := shared.ParseBooleanParam(q, "experimental")
    53  	if val != nil {
    54  		isExperimental = *val
    55  	}
    56  
    57  	lines, err := b.fetcher.Fetch(isExperimental)
    58  	if err != nil {
    59  		http.Error(w, err.Error(), http.StatusInternalServerError)
    60  
    61  		return
    62  	}
    63  
    64  	bsfData := shared.FilterandExtractBSFData(lines, from, to)
    65  	marshalled, err := json.Marshal(bsfData)
    66  	if err != nil {
    67  		http.Error(w, err.Error(), http.StatusInternalServerError)
    68  
    69  		return
    70  	}
    71  
    72  	_, err = w.Write(marshalled)
    73  	// nolint:godox // TODO: Golangci-lint found that we previously ignored the error.
    74  	// We should investigate if we should return a HTTP error or not. In the meantime, we log the error.
    75  	if err != nil {
    76  		logger := shared.GetLogger(r.Context())
    77  		logger.Warningf("Failed to write data: %s", err.Error())
    78  	}
    79  }