/ api

Validasi HTTP Cache dengan ETag

Http memiliki cara untuk memvalidasi cache, salah satunya dengan Etag Header. Header respon ETag adalah pengenal untuk versi Resource. Hal ini memungkinkan cache menjadi lebih efisien, dan menghemat bandwidth, karena server web tidak perlu mengirim tanggapan penuh jika kontennya tidak berubah. Di sisi lain, jika konten telah berubah, etag berguna untuk membantu mencegah pembaruan Resource secara simultan saling menimpa.

Strategi validasi cache dengan Etag:

  1. Kirim Request ke Resource Endpoint.
    misal:

    GET /resources
    

Response:

    HTTP/1.0 200 OK
    Host: localhost:8000
    Cache-Control: max-age=3600, public
    Date: Thu, 21 Dec 2017 02:13:17 GMT
    Content-Type: application/json
    ETag: "418f02c60c5c542152172b1e9aacf085"

    {"data":{"tes":"tes1ddfs"}}
  1. Simpan ETag dan respon body pada client cache, misal javascript sessionStorage atau localStorage. Gunakan Etag ini untuk request selanjutnya.

  2. Validasi Cache pada request selanjutnya dengan parameter header If-None-Match yang berisi ETag

     curl -X GET \
     http://localhost:8000/resources \
     -H 'If-None-Match: 418f02c60c5c542152172b1e9aacf085'
    

    Jika ETag tidak berubah maka beri respon 304 Not Modified dengan respon body kosong untuk memberitahu client bahwa Resource yang ada di lokal storage bisa digunakan.

    Jika ETag berubah, maka respon seperti pada nomor 1.


Mendapatkan ETag

ETag dapat didapatkan dengan Resource Hash, bisa menggunakan md5. Berikut contoh di Lumen Middleware untuk hashing resource ke ETag.

<?php

namespace App\Http\Middleware;

use Closure;

class EtagMiddleware {
    /**
     * Implement Etag support
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        // Get response
        $response = $next($request);
        // If this was a GET request...
        if ($request->isMethod('get')) {
            // Generate Etag
            $etag = md5($response->getContent());
            $requestEtag = str_replace('"', '', $request->getETags());
            // Check to see if Etag has changed
            if($requestEtag && $requestEtag[0] == $etag) {
                $response->setNotModified();
            }
            // Set Etag
            $response->setEtag($etag);
        }
        // Send response
        return $response;
    }
}