キャッシング
キャッシング(caching)は、特定のリソースのコピーを保存し、要求された時にそれを提供する技術である。
キャッシングを使用してネットワークを最適化することで、以下のようにサービスの品質全体を向上させる。
- バンド幅の削減
- レイテンシーの削減
- サーバーへの負荷の削減
- ネットワークの障害を隠す
REST apiのキャッシング
GETリクエストは、デフォルトでキャッシュ可能であるべきである。ブラウザは、通常全てのGETリクエストをキャッシュ可能として扱う。
POSTリクエストは、デフォルトでキャッシュ不可である。Expiresヘッダ又はCache-Controlヘッダを設定すると、キャッシュ可能になる。
PUT及びDELETEリクエストはキャッシュ不可である。
キャッシングヘッダ
キャッシングヘッダ(Cache Headers)は、RESP APIにおけるキャッシングの重要な部分である。キャッシングヘッダはクライアントに対してリソースのキャッシュ可能性の情報を提供する。最も一般的なキャッシュヘッダ:
- Cache-Control
- Expires
- ETag
- Last-Modified
Cache-Control
Cache-Controlヘッダーは、クライアントに対してキャッシュの指示を指定するためのものである。最も一般的なディレクティブのいくつかは以下の通りです:
- public: レスポンスはどのキャッシュでもキャッシュ可能。
- private: レスポンスはクライアントのブラウザキャッシュだけでキャッシュ可能。
- no-cache: レスポンスはキャッシュされたコピーを使用する前に検証する必要がある
- no-store: レスポンスはどこにもキャッシュされないべき。
- max-age: レスポンスがキャッシュできる最大の時間(秒単位)
node.jsの例:
const express = require('express');
const app = express();
app.get('/api/cachedData', (req, res) => {
res.set('Cache-Control', 'public, max-age=1000');
res.json({ message: 'Hello world. This is a cached data.' });
});
app.listen(3000, () => console.log('Server listening on port 3000'));const express = require('express');
次、curlでテストする。
$ curl -v http://localhost:3000/api/cachedData
* Trying 127.0.0.1:3000...
* Connected to localhost (127.0.0.1) port 3000 (#0)
> GET /api/cachedData HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/7.79.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Cache-Control: public, max-age=1000
< Content-Type: application/json; charset=utf-8
< Content-Length: 49
< ETag: W/"31-y/DCZtuS4N3R0s0BWizoxeyiX6E"
< Date: Sun, 19 Nov 2023 14:32:19 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
<
* Connection #0 to host localhost left intact
{"message":"Hello world. This is a cached data."}%
「Cache-Control: public, max-age=1000」が確認できた。
Expires
Expiresヘッダーは、キャッシュされたレスポンスが古くなる(stale)具体的な日時を指定する。
node.jsの例
const express = require('express');
const app = express();
app.get('/api/cachedData', (req, res) => {
const expiryDate = new Date(Date.now() + 3600 * 1000);
res.set('Expires', expiryDate.toUTCString());
res.json({ message: 'Cached data with expiry' });
});
app.listen(3000, () => console.log('Server listening on port 3000'));
curlでテストする、
$ curl -v http://localhost:3000/api/cachedData
* Trying 127.0.0.1:3000...
* Connected to localhost (127.0.0.1) port 3000 (#0)
> GET /api/cachedData HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/7.79.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Expires: Sun, 19 Nov 2023 15:35:04 GMT
< Content-Type: application/json; charset=utf-8
< Content-Length: 37
< ETag: W/"25-qaOhAnwI84qys32mcK7UPUI8LcE"
< Date: Sun, 19 Nov 2023 14:35:04 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
<
* Connection #0 to host localhost left intact
{"message":"Cached data with expiry"}%
「Date: Sun, 19 Nov 2023 14:35:04 GMT」と「Expires: Sun, 19 Nov 2023 15:35:04 GMT」により、 expiryDate = new Date(Date.now() + 3600 * 1000)
が確認できた。
ETag
Etagヘッダーは、特定のリソースの特定バージョンの一意の識別子である。
node.jsの例
const express = require('express');
const app = express();
app.get('/api/cachedData',(req, res) => {
const data = { message: 'ETag example' };
const etag = generateETag(data); // Assume generateETag is a custom function that generates an ETag for the given data
res.set('ETag', etag);
res.json(data);
});
app.listen(3000, () => console.log('Server listening on port 3000'));
function generateETag(data) {
// Implement your custom ETag generation logic here, e.g., a hash of the data
return require('crypto').createHash('md5').update(JSON.stringify(data)).digest('hex');
}
curlでテストする、
$ curl -v http://localhost:3000/api/cachedData
* Trying 127.0.0.1:3000...
* Connected to localhost (127.0.0.1) port 3000 (#0)
> GET /api/cachedData HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/7.79.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< X-Powered-By: Express
< ETag: ee8963b1f82a8785673ff212daae5f90
< Content-Type: application/json; charset=utf-8
< Content-Length: 26
< Date: Sun, 19 Nov 2023 14:37:33 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
<
* Connection #0 to host localhost left intact
{"message":"ETag example"}%
「ETag: ee8963b1f82a8785673ff212daae5f90」である。
Last-Modified
Last-Modifiedヘッダーは、リソースが最後に変更された日時を示す。
node.jsの例
const express = require('express');
const app = express();
app.get('/api/cachedData', (req, res) => {
const lastModifiedDate = new Date();
res.set('Last-Modified', lastModifiedDate.toUTCString());
res.json({ message: 'Last-Modified example' });
});
app.listen(3000, () => console.log('Server listening on port 3000'));
curlでテストする、
$ curl -v http://localhost:3000/api/cachedData
* Trying 127.0.0.1:3000...
* Connected to localhost (127.0.0.1) port 3000 (#0)
> GET /api/cachedData HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/7.79.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Last-Modified: Sun, 19 Nov 2023 14:39:36 GMT
< Content-Type: application/json; charset=utf-8
< Content-Length: 35
< ETag: W/"23-idYE3NoGknldNZGWvPSFSOLhjcY"
< Date: Sun, 19 Nov 2023 14:39:36 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
<
* Connection #0 to host localhost left intact
{"message":"Last-Modified example"}%
「Last-Modified: Sun, 19 Nov 2023 14:39:36 GMT」が確認できた。