クッキーの誕生
HTTPプロトコルは無国籍であるため、サーバー側のサービスはステートフルでなければなりません。 Cookieの誕生の本来の目的は、サーバー側で簡単に使用できるようにステータス情報をWebに保存することでした。たとえば、ユーザーが初めてウェブサイトにアクセスしているかどうかを判断します。最新の仕様はRFC 6265で、ブラウザサーバーによって実装された仕様です。
Cookieの処理は以下に分割されます。
サーバーはクライアントのようなCookieを送信します
ブラウザはCookieを保存します
その後、HTTP要求が要求されるたびに、ブラウザはCookieをサーバーに送信します。
サーバー側を送信して解析します
クッキーを送信します
クライアントが送信したサーバー側のCookieは、HTTP応答パケットを介して実装されます。セットクーキーでは、クライアントが送信する必要があるCookieが設定されています。 Cookie形式は次のとおりです。
set-cookie: "name = value; domain = .domain.com; path =/; expires = sat、2016年6月11日11:29:42 gmt; httponly; secure"
name = valueが必要なオプションであり、その他はオプションです。 Cookieの主なコンポーネントは次のとおりです。
名前:ユニークで明確なクッキー名。一般的に言えば、Cookieの名前はケースに依存しません。
値:Cookieに保存されている文字列値。 Cookieの名前と価値をエンコードするのが最善です
ドメイン:Cookieは、どのドメインに対して有効です。このドメインに送信されたすべての要求には、このCookie情報が含まれます。この値にはサブドメインを含めることができます(次のようです。
yq.aliyun.com)またはそれを含めることができません(たとえば:.aliyun.com、Aliyun.comのすべてのサブドメインに有効です)。
パス:このクッキーの影響を受けるパスを示します。ブラウザは、指定されたドメインで一致するパスなど、この構成に基づいてCookieを送信します。
有効期限:有効期限、タイムスタンプCookieをいつ削除する必要があるかを示す(つまり、Cookieをサーバーに送信するのを停止する必要がある)。このタイムスタンプを設定しない場合、ブラウザはページが閉じているときにすべてのCookieを削除します。ただし、削除時間を自分で設定することもできます。この値はGMT時間形式です。クライアントとサーバーの時間が一貫していない場合、使用すると失効すると逸脱があります。
MAX-AGE:有効期限と同じ関数は、固定時期ではなく、このCookieが(秒単位で)期限切れになる時間をブラウザに伝えるために使用されます。通常の状況では、最大年齢は期限が切れるよりも優先度が高くなります。
httponly:script document.cookieがこの値を変更できるようにしないようにブラウザに通知します。この値はdocument.cookieでも表示されません。ただし、このCookieはまだHTTPリクエストで運ばれます。この値はスクリプトでは使用できませんが、ブラウザインストールディレクトリにはファイルとして存在することに注意してください。この設定は通常、サーバー側に設定されます。
セキュア:セキュリティフラグは、指定した後、SSLリンクを使用する場合にのみサーバーに送信できます。 HTTPリンクの場合、この情報は渡されません。安全な属性が設定されていても、他の人がマシンに局所的に保存されているCookie情報を見ることができないという意味ではないので、重要な情報をCookieに入れてサーバー側に設定しないでください。
Cookieの例は次のとおりです。
var http = require( 'http'); var fs = require( 'fs'); http.createServer(function(req、res){res.setheader( 'status'、 '200 ok'); res.setheader( 'set-cookie'、 'isvisit = true; domain =。 world '); res.end();})。Set-Cookieを直接設定することはオリジナルすぎます。次のように、Cookie設定プロセスをカプセル化できます。
var serilize = function(name、val、options){if(!name){throw new error( "cooleie bese hame name"); } var enc = encodeuricomponent; var parts = []; val =(val!== null && val!== undefined)? Val.ToString(): "";オプション=オプション|| {}; parts.push(enc(name) + "=" + enc(val)); //ドメインに2つのドットが必要ですif(options.domain){parts.push( "domain =" + options.domain); } if(options.path){parts.push( "path =" + options.path); } //設定しない場合、有効期限が切れなくなり、最大年齢のブラウザは、(options.expires){parts.push( "expires =" + options.expires.togmtstring()); } if(options.maxage && typeof options.maxage === "number"){parts.push( "max-age =" + options.maxage); } if(options.httponly){parts.push( "httponly"); } if(options.secure){parts.push( "secure"); } parts.join( ";");}を返しますCookieが過去の時間に設定されている場合、ブラウザはすぐにCookieを削除することに注意する必要があります。さらに、ドメインアイテムには2つのポイントが必要なため、localhostに設定することはできません。
ここで私には明確にされておらず、しばらく私を完全に混乱させたことは、ドメイン名に少なくとも2つのドットが含まれている必要があるということでした(。)。したがって、「ローカルホスト」は無効であり、ブラウザはCookieの設定を拒否します!
サーバー側の分析Cookie
Cookieは異なるドメインとパスを設定できるため、同じ名前の値に対して、異なるドメインと異なるパスの異なるパスの下で繰り返すことができます。ブラウザは、現在の要求されているURLまたはページアドレスに最適な順序で注文を並べ替えます。
したがって、Cookieが現在の側のサーバー側に渡された場合、複数の重複した名前の値が必要な場合、最も一致するもの、つまり最初の値のみが必要です。サーバー側の解析コードは次のとおりです。
var parse = function(cstr){if(!cstr){return null; } var dec = decodeuricomponent; var cookies = {}; var parts = cstr.split(// s*;/s*/g); part.foreach(function(p){var pos = p.indexof( '='); // cookieが保存される前に名前と値をエンコードする必要がありますvar name = pos> -1?dec(p.substr(0、pos)):p; var val = pos> -1?dec(p.substr(pos + 1)):null; cookie [name] = val;クッキーを返します;}クライアントアクセス
ブラウザは、バックグラウンドで渡されたCookieを管理し、開発者はJavaScriptのdocument.cookiesを使用してCookieにアクセスできるようにします。しかし、このインターフェイスは非常に不自由です。使用する方法が異なるため、さまざまな動作が表示されます。
属性値を取得するために使用される場合、document.cookieは現在のページで使用可能なすべての文字列を返します(Cookieのドメイン、パス、有効期限、セキュリティ設定に基づいて)。文字列の形式は次のとおりです。
"name1 = value1; name2 = value2; name3 = value3";
値を設定するために使用すると、document.cookieプロパティは新しいCookie文字列に設定できます。この文字列は解釈され、既存のCookieコレクションに追加されます。のように:
document.cookie = "_fa = aaaffffasdsf; domain = .dojotoolkit.org; path =/"
document.cookieの設定は、既存のCookieでset name Valueドメインパスが繰り返されない限り、Cookieをオーバーライドしません。
Cookieの読み取りと書き込みは非常に不便であるため、主にCookieの追加、変更、削除のために、Cookieを処理するためのいくつかの機能をカプセル化できます。
var cookieutils = {get:function(name){var cookiename = encodeuricomponent(name) + "="; //最も一致する名前のみを取得します。valuevar cookiestart = document.cookie.indexof(cookiename); var cookievalue = null; if(cookiestart> -1){// cocitiestart var cookieend = document.cookie.indexof( ';'、cositiestart); // from = after =(cookieend> -1){cookievalue = decodeuricomponent(document.cookie.substring(cookiestart + cookiename.length、cookieend)); } else {cookievalue = decodeuricomponent(document.cookie.substring(cookiestart + cookiename.length、document.cookie.length)); }} return cookievalue; }、set:function(name、val、options){if(!name){throw new error( "cooliie bese nike name"); } var enc = encodeuricomponent; var parts = []; val =(val!== null && val!== undefined)? Val.ToString(): "";オプション=オプション|| {}; parts.push(enc(name) + "=" + enc(val)); //ドメインには、(options.domain){parts.push( "domain =" + options.domain); } if(options.path){parts.push( "path =" + options.path); } //設定しない場合、有効期限が切れなくなり、最大年齢のブラウザはページが閉じたときにクッキーをクリアします} //設定しない場合、有効期限が切れなくなり、最大年齢のブラウザはページが閉じたときにクッキーをクリアします(options.expires){parts.push( "expires =" + options.expires.togmtstring()); } if(options.maxage && typeof options.maxage === "number"){parts.push( "max-age =" + options.maxage); } if(options.httponly){parts.push( "httponly"); } if(options.secure){parts.push( "secure"); } document.cookie = parts.join( ";"); }、delete:function(name、options){options.expires = new date(0); //過去の日付this.set(name、null、options); }}キャッシュの利点
一般的にWebキャッシュと呼ばれるのは、一般的なHTTP要求のコピーを自動的に保存できるHTTPデバイスを指します。フロントエンド開発者にとって、ブラウザは重要な役割を果たします。さらに、キャッシュにも使用できるさまざまな一般的なプロキシサーバーがあります。 Web要求がキャッシュに到達すると、キャッシュはサーバーを通過せずにローカルレプリカからレプリカコンテンツを抽出します。これは次の利点をもたらします。
キャッシングにより、冗長データ送信が減少し、トラフィックが節約されます
キャッシュは、帯域幅のボトルネックの問題を軽減します。ページは、帯域幅を増やすことなく、より速くロードできます
キャッシュは、インスタント輻輳を緩和し、元のサーバーの要件を削減します。
キャッシュは、遠くの場所からページを読み込むことが遅くなるため、距離遅延を減らします。
キャッシュタイプ
キャッシュは、単一のユーザーに専念するか、複数のユーザーが共有することができます。専用のキャッシュはプライベートキャッシュと呼ばれ、共有キャッシュはパブリックキャッシュと呼ばれます。
プライベートキャッシュ
プライベートキャッシュは独自のユーザー向けのみであるため、多くのスペースを必要とせず、安価です。 Webブラウザにはプライベートキャッシュが組み込まれています。ほとんどのブラウザは、PCのディスクとメモリに一般的なリソースをキャッシュします。たとえば、Chromeブラウザのキャッシュストレージの場所は、c:/users/your_account/appdata/local/google/chrome/user data/defaultです。
パブリックキャッシュ
パブリックキャッシュは、キャッシュプロキシサーバーまたはプロキシキャッシュと呼ばれる特別な共有プロキシサーバーです(逆プロキシの目的)。パブリックキャッシュは複数のユーザーからのアクセスを受け入れるため、冗長なトラフィックをよりよく減らすことができます。
以下の図では、各クライアントはサーバーにリソースに繰り返しアクセスします(現時点ではプライベートキャッシュにはありません)。そのため、サーバーに複数回アクセスしてサーバーの圧力が増加します。共有されたパブリックキャッシュを使用する場合、キャッシュはサーバーから一度検索する必要があり、将来サーバーを通過する必要はありません。これにより、サーバーへの圧力が大幅に低下する可能性があります。
実際、階層的なパブリックキャッシュは通常、実際のアプリケーションで使用されます。基本的なアイデアは、クライアントの近くで小さく安価なキャッシュを使用することですが、より高いレベルでは、複数のユーザーが共有するリソースをロードするために、より大きく、より強力なキャッシュが徐々に採用されます。
キャッシュ処理フロー
フロントエンド開発者の場合、主にブラウザのキャッシュを扱うため、上記のプロセスは次のことを簡素化されます。
次の写真は、さまざまなリソースのウェブサイトのリクエスト結果を示しています。一部のリソースはキャッシュから直接読み取られ、一部のリソースがサーバーで再現され、一部のリソースがサーバーから再取得されることがわかります。
キャッシュリソースについて議論したすべての質問は、GETリクエストのみであることに注意してください。 Post、削除、Putなどの行動操作の場合、通常、キャッシュはありません。
新鮮さの制限
HTTPは、新鮮さの制限と呼ばれるキャッシュを介して、一定期間サーバーリソースのコピーを保持します。これにより、同じリソースが一定期間リクエストされ、サーバーを再度通過しません。 HTTPプロトコルのキャッシュ制御と有効期限は、新鮮さの制限を設定するために使用できます。前者はhttp1.1に追加された新しい応答ヘッダーで、後者はhttp1.0の応答ヘッダーです。どちらも同じことを行いますが、キャッシュコントロールは相対時間を使用しており、期限切れにはクライアントとサーバーの時間が異なるという問題があるため、キャッシュコントロールを好みます。
キャッシュ制御
キャッシュ制御によって設定できる属性値を見てみましょう。
Max-Age(ユニットはS)で、キャッシュを設定するための最大有効時間を指定します。これは、時間の長さを定義します。ブラウザがサーバーにリクエストを送信すると、ブラウザは最大時代にサーバーにリクエストを送信しなくなります。
<html> <head> <メタhttp-equiv = "content-type" content = "text /html; charset = utf-8"> <meta name = "viewport" content = "width =" width = device-width、initial-scale = 1.0、maximing-scale = 1.0、user-scalable = no " /> <meta htp-compative" x-compative content = "ie = edge"/> <title> webキャッシュ</title> <link rel = "shortcutアイコン" href = "./ shortcut.png"> <scrip> </script> </head> <body> <img src = "./ cache.png"> </body> </html> require( 'fs'); http.createserver(function(req、res){if(req.url === '/' || req.url === '' || req.url === '/index.html'){fs.readfile( './ index.html'、unternic(err、file、console.log)メインドキュメント、「キャッシュコントロール」、「最大時代」 + 5); fs.readfile( './ cache.png'、function(err、file){res.setheader( 'cache-control'、 "max-age =" + 5); })。聞く(8888)5秒以内にページに2回アクセスすると、ブラウザはキャッシュから直接リソースを取得します
パブリックは、応答をプロキシキャッシュでキャッシュできるため、複数のユーザーが共有できることを指定しています。プライベートが明示的に指定されていない場合、デフォルトで公開されます。
プライベートな応答は、プライベートキャッシュでのみキャッシュでき、プロキシキャッシュに配置することはできません。一部のユーザー情報に敏感なリソースは、通常、プライベートに設定する必要があります。
ノーキャッシュとは、ローカルキャッシュを使用するかどうかを決定する前に、最初にリソースが変更されたかどうか(if-none-matchとetagに依存する)かどうかをサーバーに確認する必要があることを意味します。
上記のcache.pngの処理が次のように変更された場合、ページにアクセスするたびに、ブラウザはリソースが変更されたかどうかを確認するためにサーバーに移動する必要があります。
fs.readfile( './ cache.png'、function(err、file){console.log(req.headers); console.log(req.url)if(!req.headers ['if-none-match']){res.setheader( 'cache-control'、 "no-cach、max-age =" + 5); 「Image/png」); res.sethers( "content-type '、' res.writehead);ノーストアは、リソースのキャッシュを絶対に禁止しています。つまり、ユーザーがリソースを要求するたびに、リクエストがサーバーに送信され、完全なリソースが毎回ダウンロードされます。通常、機密リソースに使用されます。
キャッシュコントロールの使用については、下の写真を参照してください(大量から)
クライアントの新鮮さの制限
キャッシュ制御は、応答ヘッダーだけでなく、リクエストヘッダーにも設定できます。ブラウザは、リクエストヘッダーにキャッシュコントロールを設定して、キャッシュからリソースを読み取るかどうかを決定できます。これはまた、ブラウザの更新ボタンをクリックしてアドレスバーに入ってネットワークモジュールでまったく異なる結果を見ることがある理由でもあります。
期限切れ
有効期限は推奨されません。数秒ではなく、特定の有効期限を指定します。多くのサーバーとクライアントにはクロックが一貫していないため、キャッシュ制御を使用することが最善です。
サーバー検証
ブラウザまたはプロキシキャッシュの有効期限が切れるキャッシュされたリソースは、実際には元のサーバーのリソースと異なることを意味しませんが、チェックする時間であることを意味します。この状況は、サーバーの再検証と呼ばれます。
リソースが変更された場合、新しいリソースを取得し、キャッシュ内の古いリソースを交換する必要があります。
リソースが変更されていない場合、キャッシュは、キャッシュ内のリソースの有効期限を更新するために、新しい応答ヘッダーと新しい有効期限を取得する必要があります。
http1.1の推奨検証方法は、if-none-match/etagであり、if modified-since/last-modifiedはhttp1.0で使用されます。
ETAGおよびIF-NONE-MATCH
エンティティコンテンツに基づいてハッシュ文字列を生成し、リソースのステータスを識別し、サーバーによって生成されます。ブラウザは、この文字列をサーバーに渡して、リソースが変更されていることを確認します。変更されていない場合、プロセスは次のとおりです(写真は、Webキャッシュに関する簡単な説明からのものです):
上記のデモでは、サーバー上のETAGを確認する方法を見てきました。
ETAGにはサーバー構造があるため、Cluster環境でETAGの独自性を確保する必要があります
if-modified-since vs. Last-Modified
これら2つは、リソースの有効期限が切れているかどうかを確認するために、HTTP 1.0で使用される要求/応答ヘッダーです。これらの2つのヘッダーは日付です。検証プロセスはETAGに似ているため、ここでは詳しく紹介しません。これら2つのヘッダーを使用して、リソースが更新されていることを確認すると、次の問題が存在します。
一部のドキュメントリソースは定期的に書き換えられますが、実際のコンテンツは変更されていません。現時点では、ファイルメタデータは、ファイルの最新の変更日がIF修正型とは異なることを示し、不要な応答をもたらします。
一部のドキュメントリソースは変更されていますが、変更の内容は重要ではなく、すべてのキャッシュを更新する必要はありません(コードコメントなど)
キャッシュの更新については、Zhang Yunlongの回答をご覧ください。この記事は詳細に拡張されません。
この記事のデモコードは次のとおりです。
<!doctype html> <html> <head> <meta http-equiv = "content-type" content = "text /html; charset = utf-8"> <meta name = "viewport" content = " http-equiv = "x-ua-compatible" content = "ie = edge"/> <title> webキャッシュ</title> <link rel = "shortcutアイコン" href = "./ shortcut.png"> </script> </head> <body> <body> <img src = "。 require( 'http'); var fs = require( 'fs'); http.createServer(function(req、res){if(req.url === '/' || req.url === '' || req.url === '/andex.html') console.log(req.url)メインドキュメントの設定'/shortcut.png'){fs.readfile( './ shortcut.png'、function(err、file){console.log(req.url)res.setheader( 'content-type'、 'images/png'); res.writehead( '200'、 "ok"); '/cache.png'){fs.readfile( './ cache.png'、function(err、file){console.log(req.headers); console.log(req.url)if(!req.headers ['if-none-match']){res.setheader( 'cache-control' " + 5); res.sether( 'content-type'、 "eTag '); res.seTheader( "max-age =" + 5); }})。聞く(8888)OK、この記事のクッキーの紹介はここで終わります。みんなが気に入ってくれることを願っています。