(cruds map[string]dbresourceinterface.DbResourceInterface, transaction *sqlx.Tx)
| 121 | } |
| 122 | |
| 123 | func CreateTemplateRouteHandler(cruds map[string]dbresourceinterface.DbResourceInterface, transaction *sqlx.Tx) func(template map[string]interface{}) func(ginContext *gin.Context) { |
| 124 | return func(templateInstance map[string]interface{}) func(ginContext *gin.Context) { |
| 125 | |
| 126 | templateName := templateInstance["name"].(string) |
| 127 | actionConfigInterface := templateInstance["action_config"] |
| 128 | cacheConfigInterface := templateInstance["cache_config"] |
| 129 | actionRequest, err := GetActionConfig(actionConfigInterface) |
| 130 | if err != nil { |
| 131 | log.Errorf("Failed to get template instance for template [%v]", templateName) |
| 132 | } |
| 133 | |
| 134 | var cacheConfig *CacheConfig |
| 135 | cacheConfig, err = GetCacheConfig(cacheConfigInterface) |
| 136 | if err != nil { |
| 137 | log.Errorf("Failed to get template instance for template [%v]", templateName) |
| 138 | } |
| 139 | // Get the Olric cache instance |
| 140 | log.Infof("Cache config for [%v] [%v]", templateName, cacheConfig) |
| 141 | |
| 142 | return func(c *gin.Context) { |
| 143 | |
| 144 | // Apply caching configuration if available |
| 145 | log.Tracef("Serve template[%s] request[%s]", templateName, c.Request.URL.Path) |
| 146 | if cacheConfig != nil && cacheConfig.Enable { |
| 147 | // Generate cache key first - we'll need this for both checking and creating cache |
| 148 | var cacheKey string |
| 149 | if cacheConfig.EnableInMemoryCache { |
| 150 | cacheKey = generateCacheKey(c, cacheConfig) |
| 151 | } |
| 152 | |
| 153 | // Apply cache control headers based on configuration |
| 154 | applyCacheHeaders(c, cacheConfig) |
| 155 | |
| 156 | // First check client cache validators (If-None-Match, If-Modified-Since) |
| 157 | // This should be done before checking the server cache to avoid unnecessary processing |
| 158 | if checkCacheValidators(c, cacheConfig) { |
| 159 | // Return 304 Not Modified if client has valid cached version |
| 160 | c.Writer.WriteHeader(http.StatusNotModified) |
| 161 | return |
| 162 | } |
| 163 | |
| 164 | // Then check if we can serve the response from in-memory cache |
| 165 | if cacheConfig.EnableInMemoryCache && cacheKey != "" { |
| 166 | if cachedFile, found := fileCache.Get(cacheKey); found { |
| 167 | // Check if client's ETag matches our cached ETag |
| 168 | if clientEtag := c.GetHeader("If-None-Match"); clientEtag != "" && clientEtag == cachedFile.ETag { |
| 169 | c.Header("Cache-Control", "public, max-age=31536000") // 1 year for 304 responses |
| 170 | c.Header("ETag", cachedFile.ETag) |
| 171 | c.AbortWithStatus(http.StatusNotModified) |
| 172 | return |
| 173 | } |
| 174 | |
| 175 | // Set basic headers from cache |
| 176 | c.Header("Content-Type", cachedFile.MimeType) |
| 177 | c.Header("ETag", cachedFile.ETag) |
| 178 | |
| 179 | // Set cache control based on expiry time |
| 180 | maxAge := int(time.Until(cachedFile.ExpiresAt).Seconds()) |
no test coverage detected