trafficcontrol-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mitchell...@apache.org
Subject [trafficcontrol] branch master updated: Return last-modified header only in case of IMS requests (#5142)
Date Fri, 16 Oct 2020 01:43:29 GMT
This is an automated email from the ASF dual-hosted git repository.

mitchell852 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git


The following commit(s) were added to refs/heads/master by this push:
     new 5dcef0a  Return last-modified header only in case of IMS requests (#5142)
5dcef0a is described below

commit 5dcef0aeb410a5b2a57429f2e52279f08e03ac15
Author: Srijeet Chatterjee <30329068+srijeet0406@users.noreply.github.com>
AuthorDate: Thu Oct 15 19:37:59 2020 -0600

    Return last-modified header only in case of IMS requests (#5142)
    
    * Return last-modified header only in case of IMS requests
    
    * disables caching in TP until it utilizes IMS
    
    Co-authored-by: Jeremy Mitchell <mitchell852@gmail.com>
---
 CHANGELOG.md                                       |  1 +
 .../traffic_ops_golang/api/shared_handlers.go      | 14 +++++-
 .../traffic_ops_golang/api/shared_handlers_test.go | 58 +++++++++++++++++++++-
 .../deliveryservice/servers/servers.go             | 14 ++++--
 .../federation_resolvers/federation_resolvers.go   |  8 +--
 .../federations/allfederations.go                  |  6 +--
 .../traffic_ops_golang/federations/federations.go  |  2 +-
 traffic_ops/traffic_ops_golang/server/servers.go   |  2 +-
 traffic_portal/app/src/app.js                      | 10 +++-
 9 files changed, 101 insertions(+), 14 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e6988e4..f357870 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -109,6 +109,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
 - Changed some Traffic Ops Go Client methods to use `DeliveryServiceNullable` inputs and
outputs.
 - When creating invalidation jobs through TO/TP, if an identical regex is detected that overlaps
its time, then warnings
 will be returned indicating that overlap exists.
+- Changed Traffic Portal to disable browser caching on GETs until it utilizes the If-Modified-Since
functionality that the TO API now provides.
 - Changed Traffic Portal to use Traffic Ops API v3
 - Changed Traffic Portal to use the more performant and powerful ag-grid for all server and
invalidation request tables.
 - Changed ORT Config Generation to be deterministic, which will prevent spurious diffs when
nothing actually changed.
diff --git a/traffic_ops/traffic_ops_golang/api/shared_handlers.go b/traffic_ops/traffic_ops_golang/api/shared_handlers.go
index 942db70..bed554d 100644
--- a/traffic_ops/traffic_ops_golang/api/shared_handlers.go
+++ b/traffic_ops/traffic_ops_golang/api/shared_handlers.go
@@ -130,6 +130,18 @@ func checkIfOptionsDeleter(obj interface{}, params map[string]string)
(bool, err
 	return false, errors.New("Refusing to delete all resources of type " + name), nil, http.StatusBadRequest
 }
 
+// SetLastModifiedHeader sets the Last-Modified header in case the "useIMS" is set to true
in the config,
+// and if there is an "If-Modified-Since" header in the incoming request
+func SetLastModifiedHeader(r *http.Request, useIMS bool) bool {
+	if r == nil {
+		return false
+	}
+	if r.Header.Get(rfc.IfModifiedSince) != "" && useIMS {
+		return true
+	}
+	return false
+}
+
 // ReadHandler creates a handler function from the pointer to a struct implementing the Reader
interface
 //      this handler retrieves the user from the context
 //      combines the path and query parameters
@@ -166,7 +178,7 @@ func ReadHandler(reader Reader) http.HandlerFunc {
 			HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
 			return
 		}
-		if maxTime != nil {
+		if maxTime != nil && SetLastModifiedHeader(r, useIMS) {
 			// RFC1123
 			date := maxTime.Format("Mon, 02 Jan 2006 15:04:05 MST")
 			w.Header().Add(rfc.LastModified, date)
diff --git a/traffic_ops/traffic_ops_golang/api/shared_handlers_test.go b/traffic_ops/traffic_ops_golang/api/shared_handlers_test.go
index 260343f..b42e88a 100644
--- a/traffic_ops/traffic_ops_golang/api/shared_handlers_test.go
+++ b/traffic_ops/traffic_ops_golang/api/shared_handlers_test.go
@@ -29,6 +29,7 @@ import (
 	"testing"
 	"time"
 
+	"github.com/apache/trafficcontrol/lib/go-rfc"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/auth"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/config"
 	"github.com/jmoiron/sqlx"
@@ -44,7 +45,7 @@ type tester struct {
 	errCode     int   //only for testing
 }
 
-var cfg = config.Config{ConfigTrafficOpsGolang: config.ConfigTrafficOpsGolang{DBQueryTimeoutSeconds:
20}}
+var cfg = config.Config{ConfigTrafficOpsGolang: config.ConfigTrafficOpsGolang{DBQueryTimeoutSeconds:
20}, UseIMS: true}
 
 func (i tester) GetKeyFieldsInfo() []KeyFieldInfo {
 	return []KeyFieldInfo{{"id", GetIntKey}}
@@ -83,6 +84,15 @@ func (i *tester) Create() (error, error, int) {
 
 //Reader interface functions
 func (i *tester) Read(h http.Header, useIMS bool) ([]interface{}, error, error, int, *time.Time)
{
+	if h.Get(rfc.IfModifiedSince) != "" {
+		if imsDate, ok := rfc.ParseHTTPDate(h.Get(rfc.IfModifiedSince)); !ok {
+			return []interface{}{tester{ID: 1}}, nil, nil, http.StatusOK, nil
+		} else {
+			if imsDate.UTC().After(time.Now().UTC()) {
+				return []interface{}{}, nil, nil, http.StatusNotModified, &imsDate
+			}
+		}
+	}
 	return []interface{}{tester{ID: 1}}, nil, nil, http.StatusOK, nil
 }
 
@@ -187,6 +197,52 @@ func TestReadHandler(t *testing.T) {
 	if w.Body.String() != body {
 		t.Error("Expected body", body, "got", w.Body.String())
 	}
+	if w.Result().Header.Get(rfc.LastModified) != "" {
+		t.Errorf("Expected no last modified header (since this is a non IMS request), but got %v",
w.Result().Header.Get(rfc.LastModified))
+	}
+}
+
+func TestReadHandlerIMS(t *testing.T) {
+	mockDB, mock, err := sqlmock.New()
+	if err != nil {
+		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+	}
+	defer mockDB.Close()
+
+	db := sqlx.NewDb(mockDB, "sqlmock")
+	defer db.Close()
+
+	w := httptest.NewRecorder()
+	r, err := http.NewRequest("", "", nil)
+	if err != nil {
+		t.Error("Error creating new request")
+	}
+
+	ctx := r.Context()
+	ctx = context.WithValue(ctx, auth.CurrentUserKey,
+		auth.CurrentUser{UserName: "username", ID: 1, PrivLevel: auth.PrivLevelAdmin})
+	ctx = context.WithValue(ctx, PathParamsKey, map[string]string{"id": "1"})
+	ctx = context.WithValue(ctx, DBContextKey, db)
+	ctx = context.WithValue(ctx, ConfigContextKey, &cfg)
+	ctx = context.WithValue(ctx, ReqIDContextKey, uint64(0))
+	futureTime := time.Now().AddDate(0, 0, 1)
+	time := futureTime.Format(time.RFC1123)
+	r.Header.Add(rfc.IfModifiedSince, time)
+	// Add our context to the request
+	r = r.WithContext(ctx)
+	readFunc := ReadHandler(&tester{})
+
+	mock.ExpectBegin()
+	mock.ExpectCommit()
+
+	readFunc(w, r)
+
+	if w.Result().StatusCode != http.StatusNotModified {
+		t.Errorf("Expected status code of 304, got %v instead", w.Result().StatusCode)
+	}
+	if w.Result().Header.Get(rfc.LastModified) == "" {
+		t.Error("Expected a valid last modified header, but got nothing")
+	}
 }
 
 func TestUpdateHandler(t *testing.T) {
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go
index 5942f7f..209fda6 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/servers/servers.go
@@ -108,6 +108,14 @@ func (dss *TODeliveryServiceServer) Validate(tx *sql.Tx) error {
 
 // ReadDSSHandler list all of the Deliveryservice Servers in response to requests to api/1.1/deliveryserviceserver$
 func ReadDSSHandler(w http.ResponseWriter, r *http.Request) {
+	useIMS := false
+	cfg, err := api.GetConfig(r.Context())
+	if err != nil {
+		log.Warnf("Couldnt get the config %v", err)
+	}
+	if cfg != nil {
+		useIMS = cfg.UseIMS
+	}
 	inf, userErr, sysErr, errCode := api.NewInfo(r, nil, []string{"limit", "page"})
 	if userErr != nil || sysErr != nil {
 		api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
@@ -117,12 +125,12 @@ func ReadDSSHandler(w http.ResponseWriter, r *http.Request) {
 
 	dss := TODeliveryServiceServer{}
 	dss.SetInfo(inf)
-	results, err, maxTime := dss.readDSS(nil, inf.Tx, inf.User, inf.Params, inf.IntParams, nil,
nil, false)
+	results, err, maxTime := dss.readDSS(nil, inf.Tx, inf.User, inf.Params, inf.IntParams, nil,
nil, useIMS)
 	if err != nil {
 		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, err)
 		return
 	}
-	if maxTime != nil {
+	if maxTime != nil && api.SetLastModifiedHeader(r, useIMS) {
 		// RFC1123
 		date := maxTime.Format("Mon, 02 Jan 2006 15:04:05 MST")
 		w.Header().Add(rfc.LastModified, date)
@@ -184,7 +192,7 @@ func ReadDSSHandlerV14(w http.ResponseWriter, r *http.Request) {
 	}
 
 	results, err, maxTime := dss.readDSS(r.Header, inf.Tx, inf.User, inf.Params, inf.IntParams,
dsIDs, serverIDs, useIMS)
-	if maxTime != nil {
+	if maxTime != nil && api.SetLastModifiedHeader(r, useIMS) {
 		// RFC1123
 		date := maxTime.Format("Mon, 02 Jan 2006 15:04:05 MST")
 		w.Header().Add(rfc.LastModified, date)
diff --git a/traffic_ops/traffic_ops_golang/federation_resolvers/federation_resolvers.go b/traffic_ops/traffic_ops_golang/federation_resolvers/federation_resolvers.go
index 2cc48d7..ff53baa 100644
--- a/traffic_ops/traffic_ops_golang/federation_resolvers/federation_resolvers.go
+++ b/traffic_ops/traffic_ops_golang/federation_resolvers/federation_resolvers.go
@@ -185,9 +185,11 @@ func Read(w http.ResponseWriter, r *http.Request) {
 		resolvers = append(resolvers, resolver)
 	}
 
-	// RFC1123
-	date := maxTime.Format("Mon, 02 Jan 2006 15:04:05 MST")
-	w.Header().Add(rfc.LastModified, date)
+	if api.SetLastModifiedHeader(r, useIMS) {
+		// RFC1123
+		date := maxTime.Format("Mon, 02 Jan 2006 15:04:05 MST")
+		w.Header().Add(rfc.LastModified, date)
+	}
 	api.WriteResp(w, r, resolvers)
 }
 
diff --git a/traffic_ops/traffic_ops_golang/federations/allfederations.go b/traffic_ops/traffic_ops_golang/federations/allfederations.go
index 4f896a1..cf5539b 100644
--- a/traffic_ops/traffic_ops_golang/federations/allfederations.go
+++ b/traffic_ops/traffic_ops_golang/federations/allfederations.go
@@ -57,7 +57,7 @@ func GetAll(w http.ResponseWriter, r *http.Request) {
 		cdnName := tc.CDNName(cdnParam)
 		feds, err, code, maxTime = getAllFederationsForCDN(inf.Tx.Tx, cdnName, useIMS, r.Header)
 		if code == http.StatusNotModified {
-			if maxTime != nil {
+			if maxTime != nil && api.SetLastModifiedHeader(r, useIMS) {
 				// RFC1123
 				date := maxTime.Format("Mon, 02 Jan 2006 15:04:05 MST")
 				w.Header().Add(rfc.LastModified, date)
@@ -74,7 +74,7 @@ func GetAll(w http.ResponseWriter, r *http.Request) {
 	} else {
 		feds, err, code, maxTime = getAllFederations(inf.Tx.Tx, useIMS, r.Header)
 		if code == http.StatusNotModified {
-			if maxTime != nil {
+			if maxTime != nil && api.SetLastModifiedHeader(r, useIMS) {
 				// RFC1123
 				date := maxTime.Format("Mon, 02 Jan 2006 15:04:05 MST")
 				w.Header().Add(rfc.LastModified, date)
@@ -91,7 +91,7 @@ func GetAll(w http.ResponseWriter, r *http.Request) {
 
 	fedsResolvers, err, code, maxTime := getFederationResolvers(inf.Tx.Tx, fedInfoIDs(feds),
useIMS, r.Header)
 	if code == http.StatusNotModified {
-		if maxTime != nil {
+		if maxTime != nil && api.SetLastModifiedHeader(r, useIMS) {
 			// RFC1123
 			date := maxTime.Format("Mon, 02 Jan 2006 15:04:05 MST")
 			w.Header().Add(rfc.LastModified, date)
diff --git a/traffic_ops/traffic_ops_golang/federations/federations.go b/traffic_ops/traffic_ops_golang/federations/federations.go
index 8647190..42e3e3f 100644
--- a/traffic_ops/traffic_ops_golang/federations/federations.go
+++ b/traffic_ops/traffic_ops_golang/federations/federations.go
@@ -114,7 +114,7 @@ func Get(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 	allFederations := addResolvers([]tc.IAllFederation{}, feds, fedsResolvers)
-	if maxTime != nil {
+	if maxTime != nil && api.SetLastModifiedHeader(r, useIMS) {
 		// RFC1123
 		date := maxTime.Format("Mon, 02 Jan 2006 15:04:05 MST")
 		w.Header().Add(rfc.LastModified, date)
diff --git a/traffic_ops/traffic_ops_golang/server/servers.go b/traffic_ops/traffic_ops_golang/server/servers.go
index 7d503fd..8e5df19 100644
--- a/traffic_ops/traffic_ops_golang/server/servers.go
+++ b/traffic_ops/traffic_ops_golang/server/servers.go
@@ -651,7 +651,7 @@ func Read(w http.ResponseWriter, r *http.Request) {
 	}
 
 	servers, serverCount, userErr, sysErr, errCode, maxTime = getServers(r.Header, inf.Params,
inf.Tx, inf.User, useIMS, *version)
-	if maxTime != nil {
+	if maxTime != nil && api.SetLastModifiedHeader(r, useIMS) {
 		// RFC1123
 		date := maxTime.Format("Mon, 02 Jan 2006 15:04:05 MST")
 		w.Header().Add(rfc.LastModified, date)
diff --git a/traffic_portal/app/src/app.js b/traffic_portal/app/src/app.js
index ad83c4b..0bdf95f 100644
--- a/traffic_portal/app/src/app.js
+++ b/traffic_portal/app/src/app.js
@@ -521,5 +521,13 @@ trafficPortal.factory('authInterceptor', function ($rootScope, $q, $window,
$loc
 });
 
 trafficPortal.config(function ($httpProvider) {
-    $httpProvider.interceptors.push('authInterceptor');
+        $httpProvider.interceptors.push('authInterceptor');
+
+        // disabling caching for TP until it utilizes If-Modified-Since
+        if (!$httpProvider.defaults.headers.get) {
+                $httpProvider.defaults.headers.get = {};
+        }
+        $httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache, no-store, must-revalidate';
+        $httpProvider.defaults.headers.get['Pragma'] = 'no-cache';
+        $httpProvider.defaults.headers.get['Expires'] = 0;
 });


Mime
View raw message