Node.js HTTPサーバーで単一のCookieを取得および設定する


159

単一のCookieを設定し、nodejsサーバーインスタンスに対して行われる各要求でその単一のCookieを読み取ることができるようにしたいと考えています。サードパーティのlibを取り込む必要なしに、それを数行のコードで実行できますか?

var http = require('http');

http.createServer(function (request, response) {
  response.writeHead(200, {'Content-Type': 'text/plain'});
  response.end('Hello World\n');
}).listen(8124);

console.log('Server running at http://127.0.0.1:8124/');

上記のコードを直接nodejs.orgから取得し、それにcookieを挿入するだけです。

回答:


190

クッキーを取得/設定するための迅速な機能アクセスがないため、次のハックを思いつきました:

var http = require('http');

function parseCookies (request) {
    var list = {},
        rc = request.headers.cookie;

    rc && rc.split(';').forEach(function( cookie ) {
        var parts = cookie.split('=');
        list[parts.shift().trim()] = decodeURI(parts.join('='));
    });

    return list;
}


http.createServer(function (request, response) {

  // To Read a Cookie
  var cookies = parseCookies(request);

  // To Write a Cookie
  response.writeHead(200, {
    'Set-Cookie': 'mycookie=test',
    'Content-Type': 'text/plain'
  });
  response.end('Hello World\n');
}).listen(8124);

console.log('Server running at http://127.0.0.1:8124/');

これにより、すべてのCookieがCookieオブジェクトに格納され、ヘッドを書き込むときにCookieを設定する必要があります。


11
上記のコードは=、FacebookのCookieのように、Cookieの値に等号()が含まれていると正しく機能しませんfbm_1234123412341234=base_domain=.domain.com
2012年

3
Cookieの値をURLエンコード/パーセントエンコードする必要はありませんか?= doockieの値はその場合無効になりますよね?
les2 2013年

2
その場合、;それまでにの最初のインスタンスで分割されます=。左がキー、右が値です。
iLoch

4
私は、スイッチの代わりに@iLoch Iのルートを行くの、@Eyeと同じ問題に遭遇parts[0]するparts.shift()parts[1]parts.join('=')
aron.duby

3
与えられたコードには深刻なバグがあり、人々はそれをコピーすることを試みました。私の最後の更新を参照してください
Dan

124

多くのnode.js開発者が行うように、エクスプレスライブラリを使用している場合は、もっと簡単な方法があります。詳細については、Express.jsのドキュメントページを確認してください。

上記の構文解析の例は機能しますが、expressはそれを処理する優れた機能を提供します。

app.use(express.cookieParser());

クッキーを設定するには:

res.cookie('cookiename', 'cookievalue', { maxAge: 900000, httpOnly: true });

Cookieをクリアするには:

res.clearCookie('cookiename');

14
cookieライブラリは、実際には基礎となるライブラリ接続からのものです。cookieヘルパーを取得するために、すべてのエクスプレスを取る必要はありません。
Ajaxの

1
実際にはCookieライブラリは接続の一部ではありません(Cookieを設定できません)
2012年

10
cookie-parserExpressやConnectの一部ではなくなりましたが、ミドルウェアとして利用できます:github.com/expressjs/cookie-parser
Koen。

7
この例では、どのようにしてCookieを「取得」しますか?完全性と質問に答えるため。
過激な2015

1
cookieを使用するためだけにExpressをインストールする必要があるため、反対投票
Steven

34

RevNoahは、Expressのcookieパーサーの使用を提案することで最良の回答を得ました。しかし、その答えは現在3年前のものであり、古くなっています。

Expressを使用すると、次のようにCookieを読み取ることができます

var express = require('express');
var cookieParser = require('cookie-parser');
var app = express();
app.use(cookieParser());
app.get('/myapi', function(req, resp) {
   console.log(req.cookies['Your-Cookie-Name-Here']);
})

そしてpackage.json、適切な比較的最新のバージョンに置き換えて、以下を使用してを更新します。

"dependencies": {
    "express": "4.12.3",
    "cookie-parser": "1.4.0"
  },

Cookieの設定や解析などのその他の操作については、こちらこちらをご覧ください。


8
質問は、取得設定の方法を尋ねます。セット使用するには、この:res.cookie('cookieName', cookieValue, { maxAge: 900000, httpOnly: true });
Augieガードナー

セッションごとにCookieを設定して取得できますか(キーを認識して処理する必要はありません)?
Matej J

12

@Corey Hartの回答の拡張として、次のように書き直しましたparseCookies()

これが実際の例です:

let http = require('http');

function parseCookies(str) {
  let rx = /([^;=\s]*)=([^;]*)/g;
  let obj = { };
  for ( let m ; m = rx.exec(str) ; )
    obj[ m[1] ] = decodeURIComponent( m[2] );
  return obj;
}

function stringifyCookies(cookies) {
  return Object.entries( cookies )
    .map( ([k,v]) => k + '=' + encodeURIComponent(v) )
    .join( '; ');
}

http.createServer(function ( request, response ) {
  let cookies = parseCookies( request.headers.cookie );
  console.log( 'Input cookies: ', cookies );
  cookies.search = 'google';
  if ( cookies.counter )
    cookies.counter++;
  else
    cookies.counter = 1;
  console.log( 'Output cookies: ', cookies );
  response.writeHead( 200, {
    'Set-Cookie': stringifyCookies(cookies),
    'Content-Type': 'text/plain'
  } );
  response.end('Hello World\n');
} ).listen(1234);

OPはhttpモジュールを使用することにも注意します。OPがrestifyを使用していた場合、彼はrestify-cookiesを利用できます:

var CookieParser = require('restify-cookies');
var Restify = require('restify');
var server = Restify.createServer();
server.use(CookieParser.parse);
server.get('/', function(req, res, next){
  var cookies = req.cookies; // Gets read-only cookies from the request
  res.setCookie('my-new-cookie', 'Hi There'); // Adds a new cookie to the response
  res.send(JSON.stringify(cookies));
});
server.listen(8080);

1
3.5年後の将来の視聴者向けのいくつかの提案。そのように配列を構築する代わりに、let/constand stringifyCookiesを使用して1つを並べることができますmap
Ascherer

10

包括的な機能セットを備えた「cookies」npmモジュールを使用できます。

ドキュメントと例:https :
//github.com/jed/cookies


1
そのモジュールはhttpサーバーでの使用を意図しているようです。httpクライアントでcookieを処理するcookiejarツールはありますか?基本的に私はhttpクライアントlibに伝えたいと思います:Set-Cookieヘッダーを取得した場合は、それらを自動的に覚えてから、後続のアウトバウンド要求に(ドメインが一致する場合)渡してください。
Cheeso

これは、選択したhttpクライアントライブラリの機能です。スーパーエージェントを良い例として提案できます。
ZAH

数時間後にこのlibがExpressで動作するようにしようとあきらめてください...代わりにconnectを使用してください。
enko 2013

7

Cookie値に「=」が含まれるCookieでCookieスプリッターが機能するようにするには:

var get_cookies = function(request) {
  var cookies = {};
  request.headers && request.headers.cookie.split(';').forEach(function(cookie) {
    var parts = cookie.match(/(.*?)=(.*)$/)
    cookies[ parts[1].trim() ] = (parts[2] || '').trim();
  });
  return cookies;
};

次に、個々のCookieを取得します。

get_cookies(request)['my_cookie']


2

ノードでcookieを管理するためのきちんとしたcopy-n-pasteパッチがあります。美しさのために、これをCoffeeScriptで行います。

http = require 'http'

http.IncomingMessage::getCookie = (name) ->
  cookies = {}
  this.headers.cookie && this.headers.cookie.split(';').forEach (cookie) ->
    parts = cookie.split '='
    cookies[parts[0].trim()] = (parts[1] || '').trim()
    return

  return cookies[name] || null

http.IncomingMessage::getCookies = ->
  cookies = {}
  this.headers.cookie && this.headers.cookie.split(';').forEach (cookie) ->
    parts = cookie.split '='
    cookies[parts[0].trim()] = (parts[1] || '').trim()
    return

  return cookies

http.OutgoingMessage::setCookie = (name, value, exdays, domain, path) ->
  cookies = this.getHeader 'Set-Cookie'
  if typeof cookies isnt 'object'
    cookies = []

  exdate = new Date()
  exdate.setDate(exdate.getDate() + exdays);
  cookieText = name+'='+value+';expires='+exdate.toUTCString()+';'
  if domain
    cookieText += 'domain='+domain+';'
  if path
    cookieText += 'path='+path+';'

  cookies.push cookieText
  this.setHeader 'Set-Cookie', cookies
  return

これで、期待どおりにCookieを処理できるようになります。

server = http.createServer (request, response) ->
  #get individually
  cookieValue = request.getCookie 'testCookie'
  console.log 'testCookie\'s value is '+cookieValue

  #get altogether
  allCookies = request.getCookies()
  console.log allCookies

  #set
  response.setCookie 'newCookie', 'cookieValue', 30

  response.end 'I luvs da cookies';
  return

server.listen 8080

3
coffeescript.orgの TRY COFFESCRIPTタブにそのコードをコピーして貼り付けてください。あなたの答えは私を助けました、そしてあなたがjavascriptを知っているならcoffeescriptは読むことはそれほど難しくありません。
Mattijs 2014年

1

ここでの回答が無視している質問のこの部分を繰り返します。

サードパーティのlibを取り込む必要なしに、それを数行のコードで実行できますか?


クッキーを読む

Cookieは、Cookieヘッダー付きのリクエストから読み取られます。彼らは含まnamevalue。パスが機能するため、同じ名前の複数のCookieを送信できます。NodeJSでは、すべてのCookieはCookieヘッダーで送信されるときに1つの文字列として格納されます。で分割します;。Cookieを取得すると、(存在する場合)イコールの左側にあるnameすべてがになり、その後にあるすべてがになりvalueます。一部のブラウザは、等号のないCookieを受け入れ、名前を空白と見なします。空白はCookieの一部としてカウントされません。値は二重引用符(")で囲むこともできます。値にはも含めることができます=。たとえば、formula=5+3=8は有効なCookieです。

/**
 * @param {string} [cookieString='']
 * @return {[string,string][]} String Tuple
 */
function getEntriesFromCookie(cookieString = '') {
  return cookieString.split(';').map((pair) => {
    const indexOfEquals = pair.indexOf('=');
    let name;
    let value;
    if (indexOfEquals === -1) {
      name = '';
      value = pair.trim();
    } else {
      name = pair.substr(0, indexOfEquals).trim();
      value = pair.substr(indexOfEquals + 1).trim();
    }
    const firstQuote = value.indexOf('"');
    const lastQuote = value.lastIndexOf('"');
    if (firstQuote !== -1 && lastQuote !== -1) {
      value = value.substring(firstQuote + 1, lastQuote);
    }
    return [name, value];
  });
}

const cookieEntries = getEntriesFromCookie(request.headers.Cookie); 
const object = Object.fromEntries(cookieEntries.slice().reverse());

重複した名前を想定していない場合は、オブジェクトに変換することで、物事を簡単に行うことができます。次にobject.myCookieName、値を取得するようにアクセスできます。重複が予想される場合は、を反復処理する必要がありますcookieEntries。ブラウザーは降順の優先順位でCookieをフィードするため、逆にすると、優先順位の最も高いCookieがオブジェクトに表示されます。(これ.slice()は、配列の変異を避けるためです。)


設定クッキー

「書き込み」CookieはSet-Cookie、応答のヘッダーを使用して行われます。response.headers['Set-Cookie']オブジェクトは実際には配列ですので、あなたがそれにプッシュされます。文字列を受け入れますがname、and だけではなく、より多くの値を持っていますvalue。最も難しい部分は文字列を書き込むことですが、これは1行で行うことができます。

/**
 * @param {Object} options
 * @param {string} [options.name='']
 * @param {string} [options.value='']
 * @param {Date} [options.expires]
 * @param {number} [options.maxAge]
 * @param {string} [options.domain]
 * @param {string} [options.path]
 * @param {boolean} [options.secure]
 * @param {boolean} [options.httpOnly]
 * @param {'Strict'|'Lax'|'None'} [options.sameSite]
 * @return {string}
 */
function createSetCookie(options) {
  return (`${options.name || ''}=${options.value || ''}`)
    + (options.expires != null ? `; Expires=${options.expires.toUTCString()}` : '')
    + (options.maxAge != null ? `; Max-Age=${options.maxAge}` : '')
    + (options.domain != null ? `; Domain=${options.domain}` : '')
    + (options.path != null ? `; Path=${options.path}` : '')
    + (options.secure ? '; Secure' : '')
    + (options.httpOnly ? '; HttpOnly' : '')
    + (options.sameSite != null ? `; SameSite=${options.sameSite}` : '');
}

const newCookie = createSetCookie({
  name: 'cookieName',
  value: 'cookieValue',
  path:'/',
});
response.headers['Set-Cookie'].push(newCookie);

実際にはSet-Cookieリクエストに複数のヘッダーを設定できるため、複数のCookieを設定できることに注意してください。それが配列である理由です。


外部ライブラリに関する注意:

、、またはを使用する場合はexpress、非標準のデフォルトがあることに注意してください。解析されるCookieは常にURIデコード(パーセントデコード)されます。これは、次の文字のいずれかを含む名前または値を使用する場合を意味します。これらのライブラリでは、それらの扱いが異なります。Cookieを設定する場合、Cookieはでエンコードされます。そして、もしあなたがクッキーを読んでいるなら、あなたはそれらをデコードしなければなりません。cookie-parsercookie!#$%&'()*+/:<=>?@[]^`{|}%{HEX}

たとえば、email=name@domain.comは有効なCookieですが、これらのライブラリはそれをとしてエンコードしますemail=name%40domain.com%Cookieでを使用している場合、デコードで問題が発生する可能性があります。壊されてしまいます。たとえば、以前のCookieはにsecretagentlevel=50%007and50%006なりsecretagentlevel=507and506ます。これはエッジケースですが、ライブラリを切り替える場合に注意する必要があります。

また、これらのライブラリでは、Cookieはデフォルトpath=/で設定されています。つまり、ホストへのすべてのURLリクエストでCookie が送信されます。

これらの値を自分でエンコードまたはデコードする場合は、encodeURIComponentまたはdecodeURIComponentをそれぞれ使用できます。


参照:


追加情報:


0

最初にCookieを作成し(例としてCookie内にトークンをラップしました)、それを応答として設定する必要があります。次の方法でCookieを使用するには、cookieParserをインストールします

app.use(cookieParser());

ブラウザはそれを「リソース」タブに保存し、その後すべてのリクエストに使用され、その後、初期URLをベースとして使用します

var token = student.generateToken('authentication');
        res.cookie('token', token, {
            expires: new Date(Date.now() + 9999999),
            httpOnly: false
        }).status(200).send();

サーバー側のリクエストからCookieを取得するのも簡単です。リクエストオブジェクトの 'cookie'プロパティを呼び出して、リクエストからCookieを抽出する必要があります。

var token = req.cookies.token; // Retrieving Token stored in cookies

0

の内容が気にならずcookie、使用したいだけの場合は、request(一般的なノードモジュール)を使用してこのクリーンなアプローチを試してください:

var request = require('request');
var j = request.jar();
var request = request.defaults({jar:j});
request('http://www.google.com', function () {
  request('http://images.google.com', function (error, response, body){
     // this request will will have the cookie which first request received
     // do stuff
  });
});

申し訳ありませんが、このコードは私にはまったく意味がありません。jar()Cookieの現在のリストを取得するためのかわいいメソッド名はありますか?リクエストの2つの呼び出しのポイントは何ですか?これは主に広告であり、答えではありません。
user1944491

0
var cookie = 'your_cookie';
var cookie_value;
var i = request.headers.indexOf(cookie+'=');
if (i != -1) {
  var eq = i+cookie.length+1;
  var end = request.headers.indexOf(';', eq);
  cookie_value = request.headers.substring(eq, end == -1 ? undefined : end);
}

0

一部のES5 / 6ソーサリーとRegExマジックの使用

Cookieを読み取り、クライアント側のキーと値のペアのオブジェクトに変換するオプションは、サーバー側でも使用できます。

=値にa があれば、心配ありません。=カギがあれば楽園でのトラブル。

その他の注意事項:読みやすさを主張する人もいるので、好きなように解読してください。

ノートが好き:エラーハンドラー(catchを試す)を追加しても害はありません。

const iLikeCookies = () => {
    return Object.fromEntries(document.cookie.split('; ').map(v => v.split(/=(.+)/))); 
}

const main = () => {
    // Add Test Cookies
    document.cookie = `name=Cookie Monster;expires=false;domain=localhost`
    document.cookie = `likesCookies=yes=withARandomEquals;expires=false;domain=localhost`;

    // Show the Objects
    console.log(document.cookie)
    console.log('The Object:', iLikeCookies())

    // Get a value from key
    console.log(`Username: ${iLikeCookies().name}`)
    console.log(`Enjoys Cookies: ${iLikeCookies().likesCookies}`)
}

ここに画像の説明を入力してください

何が起こっている?

iLikeCookies();後のスペース;)でCookieを分割します:

["name=Cookie Monster", "likesCookies=yes=withARandomEquals"]

次に、その配列をマップし、括弧をキャプチャ=する正規表現を使用して最初に出現する場所で分割します。

[["name", "Cookie Monster"], ["likesCookies", "yes=withARandomEquals"]]

次に、友人の `Object.fromEntriesを使用して、これをキーとvalのペアのオブジェクトにします。

Nooice。


0

私はこの単純な機能だけ渡し書いた req.headers.cookieクッキー名を

const getCookieByName =(cookies,name)=>{
    const arrOfCookies = cookies.split(' ')
    let yourCookie = null

    arrOfCookies.forEach(element => {
        if(element.includes(name)){
            yourCookie = element.replace(name+'=','')
        }
    });
    return yourCookie
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.