ETag的GET在angular js -我需要检查服务器端
本文关键字:检查 服务器端 js GET angular ETag | 更新日期: 2023-09-27 18:12:47
我正在尝试在angular JS中实现GET请求的etag,到目前为止我已经看到https://github.com/forforf/angular-etaghttps://www.npmjs.com/package/angular-http-etag还有reangular(很复杂,但很好)。他们都说它提供了对GET请求的内置支持,我认为这意味着我不必在服务器端编写任何代码(这是在c#. net中)。
我是否正确的假设,或者我必须使用CacheCow或其他东西来查找标头中的ETAG并发送304响应。
只是一个背景,我必须使用ETAG而不是缓存(角),以便从服务器获取最新的数据。
我想要一个基于$http拦截器的解决方案,因为我需要它与$http的所有用户一起工作,而且我不能像angular-http-etag那样使用$http装饰器,因为例如$translateProvider。Angular Translate中的useStaticFilesLoader使用了$http,我希望这些调用也能被缓存。
下面的解决方案是用Typescript编写的,它将从本地存储中存储/检索缓存,并且只保留最新的25个缓存项。
interface CacheObject {
data: any;
etag: string;
index: number;
}
appModule.config(['$httpProvider', ($httpProvider) => {
const cacheKey = 'add_your_unique_custom_localstorage_key_here';
const cacheSize = 25;
let index = 0;
let cache: {[key: string]: CacheObject};
const cacheString = localStorage.getItem(cacheKey);
if (cacheString == null) {
cache = Object.create(null);
} else {
cache = JSON.parse(cacheString);
let cacheEntries = Object.entries(cache);
for (const entry of cacheEntries) {
// Find largest index
const entryIndex = entry[1].index;
if (entryIndex > index) {
index = entryIndex;
}
}
if (index > Number.MAX_SAFE_INTEGER) {
// Reset cache if index gets larger than max safe int
// This is kind of a theoretical problem
cache = Object.create(null);
cacheEntries = [];
index = 0;
}
if (cacheEntries.length > cacheSize) {
// Clean up cache once in a while. Only keep the 25 newest items
const sortedCacheEntries = cacheEntries.sort((a, b) => {
return b[1].index - a[1].index;
});
sortedCacheEntries.length = cacheSize;
cache = sortedCacheEntries.reduce(
(accum, [k, v]) => {
accum[k] = v;
return accum;
},
Object.create(null),
);
}
}
$httpProvider.interceptors.push(['$q', ($q: ng.IQService) => {
return {
response: (response) => {
const headers = response.headers();
if (response.status === 200 && headers.etag) {
const cacheObject = {
data: response.data,
etag: headers.etag,
index: index++,
};
cache[response.config.url] = cacheObject;
localStorage.setItem(cacheKey, JSON.stringify(cache));
}
return response;
},
responseError: (response) => {
if (response.status === 304) {
const cacheObject = cache[response.config.url];
if (cacheObject != null) {
const data = cacheObject.data;
const dataString = JSON.stringify(data);
const clonedData = JSON.parse(dataString);
response.data = clonedData;
// Will only recover if we set status to 200
response.status = 200;
return $q.resolve(response);
}
}
return $q.reject(response);
},
request: (config) => {
const cacheObject = cache[config.url];
if (cacheObject != null) {
config.headers['If-None-Match'] = cacheObject.etag;
}
return config;
},
};
}]);
}]);
我是angular-http-etag
的作者,所以我只能直接谈论该模块的功能。它修饰了Angular的$http
服务,让你可以指定想要缓存的请求。下面是我在readme.md:
angular
.module('myApp', [
'http-etag'
])
.config(function (httpEtagProvider) {
httpEtagProvider
.defineCache('persistentCache', {
cacheService: 'localStorage'
})
})
.controller('MyCtrl', function ($http) {
var self = this
$http
.get('/my_data.json', {
etagCache: 'persistentCache'
})
.success(function (data, status, headers, config, itemCache) {
// Modify the data from the server
data._fullName = data.first_name + ' ' + data.last_name
// Update the cache with the modified data
itemCache.set(data)
// Assign to controller property
self.fullName = data._fullName
})
// Synchronous method called if request was previously cached
.cached(function (data, status, headers, config, itemCache) {
self.fullName = data._fullName
})
.error(function (data, status) {
// 304: 'Not Modified'--Etag matched, cached data is fresh
if (status != 304) alert('Request error')
})
})
服务器端唯一需要的是确保服务器正在发送ETag
响应头。您可以在这里找到有关如何在Chrome中检查响应头的信息:https://developers.google.com/web/tools/chrome-devtools/profile/network-performance/resource-loading#view-details-for-a-single-resource
嗯,对于某些服务器必须支持发布ETags和ASP。. NET MVC或Web API默认情况下不会。您必须在服务器上使用某种形式的输出缓存。
一个这样的项目是philip Woj的CacheOutput在这里
https://github.com/filipw/Strathweb.CacheOutput