Node.js HTTP 서버로 단일 쿠키 가져 오기 및 설정


159

단일 쿠키를 설정하고 nodejs 서버 인스턴스에 대한 각 요청과 함께 단일 쿠키를 읽을 수 있기를 원합니다. 타사 라이브러리를 가져올 필요없이 몇 줄의 코드로 수행 할 수 있습니까?

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에서 직접 위의 코드를 가져 와서 쿠키를 작성하십시오.

답변:


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/');

이렇게하면 모든 쿠키가 쿠키 개체에 저장되며 헤드를 작성할 때 쿠키를 설정해야합니다.


11
쿠키 값 =에 Facebook 쿠키와 같은 등호 ( ) 가 포함되어 있으면 위의 코드가 제대로 작동하지 않습니다 fbm_1234123412341234=base_domain=.domain.com.

3
쿠키 값을 URL 인코딩 / 백분율 인코딩하지 않아도됩니까? 이 경우 doockie 값에서 유효하지 않습니다.
les2

2
이 경우 ;의 첫 번째 인스턴스로 나눕니다 =. 왼쪽은 키이고 오른쪽은 값입니다.
iLoch

4
나는 스위치 대신 @iLoch I의 길을가는, @Eye과 같은 문제로 실행 parts[0]parts.shift()parts[1]parts.join('=')
aron.duby

3
주어진 코드에는 심각한 버그가 있었고 사람들은 그것을 복사하기 위해 cuntinued했습니다. 마지막 업데이트보기
Dan

124

많은 node.js 개발자가하는 것처럼 익스프레스 라이브러리를 사용하는 경우 더 쉬운 방법이 있습니다. 자세한 내용은 Express.js 설명서 페이지를 확인하십시오.

위의 구문 분석 예제는 작동하지만 express는이를 처리하는 훌륭한 기능을 제공합니다.

app.use(express.cookieParser());

쿠키를 설정하려면

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

쿠키를 지우려면 :

res.clearCookie('cookiename');

14
쿠키 라이브러리는 실제로 기본 라이브러리 연결에서 온 것입니다. 쿠키 도우미를 얻기 위해 모든 표현을 할 필요는 없습니다.
Ajax

1
실제로 쿠키 라이브러리는 쿠키를 설정할 수없는 연결의 일부가 아닙니다.
framp

10
cookie-parser더 이상 express 및 / 또는 connect의 일부가 아니지만 미들웨어로 제공됩니다 : github.com/expressjs/cookie-parser
Koen.

7
이 예제에서 쿠키를 어떻게 "얻을"까요? 완전성과 질문에 대한 답변.
hubatish

1
쿠키를 사용하기 위해 Express를 설치해야하므로 다운 보팅
Steven

34

RevNoah는 Express의 쿠키 파서 를 사용하는 것이 가장 좋습니다 . 그러나 그 대답은 이제 3 살이며 오래되었습니다.

Express를 사용하면 다음과 같이 쿠키를 읽을 수 있습니다

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"
  },

쿠키 설정 및 구문 분석과 같은 추가 작업은 여기여기에 설명 되어 있습니다.


8
질문은 어떻게 설정 하고 설정 하는지 묻습니다 . 이것을 사용하려면 :res.cookie('cookieName', cookieValue, { maxAge: 900000, httpOnly: true });
Augie Gardner

쿠키를 세션별로 설정하고 얻을 수 있습니까 (키를 알고 처리 할 필요없이)?
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/conststringifyCookies늘어서 하나가 될 수 있습니다 map배열 방식이 건설 대신.
Ascherer

10

포괄적 인 기능 세트가있는 "쿠키"npm 모듈을 사용할 수 있습니다.

https://github.com/jed/cookies의 설명서 및 예제


1
해당 모듈이 http 서버에서 사용하기위한 것 같습니다. http 클라이언트에서 쿠키를 처리하기위한 cookiejar 도구가 있습니까? 기본적으로 http 클라이언트 lib에 말하고 싶습니다. Set-Cookie 헤더가 있으면 자동으로 기억 한 다음 후속 아웃 바운드 요청을 적절하게 전달하십시오 (도메인이 일치 할 때).
Cheeso

이것은 선택한 HTTP 클라이언트 라이브러리의 기능입니다. 슈퍼 에이전트 를 좋은 예로 제시 할 수 있습니다 .
zah

이 라이브러리를 몇 시간 후에 명시 적으로 작동 시키려고 노력했습니다 ... 대신 connect를 사용하십시오.
enko

7

쿠키 스플리터가 쿠키 값에 '='인 쿠키를 사용하려면 :

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;
};

개별 쿠키를 얻으려면 다음을 수행하십시오.

get_cookies(request)['my_cookie']


2

다음은 노드에서 쿠키를 관리하기위한 깔끔한 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

이제 예상대로 쿠키를 처리 할 수 ​​있습니다.

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
단지에 TRY의 커피 스크립트 탭에서 해당 코드를 붙여 복사 coffeescript.org을 . 당신의 대답은 저에게 도움이되었으며, 자바 스크립트를 알고 있다면 커피 스크립트를 읽는 것이 어렵지 않습니다.
Mattijs

1

여기에 답이 무시하는 질문 의이 부분을 반복하겠습니다.

타사 라이브러리를 가져올 필요없이 몇 줄의 코드로 수행 할 수 있습니까?


쿠키 읽기

쿠키는 Cookie헤더 가있는 요청에서 읽습니다 . 그들은 단지 포함 namevalue. 경로가 작동하는 방식으로 인해 동일한 이름의 여러 쿠키가 전송 될 수 있습니다. NodeJS에서 모든 쿠키는 Cookie헤더에 전송 될 때 하나의 문자열로 표시됩니다 . 으로 나누었습니다 ;. 쿠키가 있으면 등호 (있는 경우)의 왼쪽에있는 name모든 것이이고 이후의 모든 것은 value입니다. 일부 브라우저는 등호가없는 쿠키를 허용하고 이름을 비워 둔 것으로 가정합니다. 공백은 쿠키의 일부로 계산되지 않습니다. 값은 큰 따옴표 ( ")로 묶을 수도 있습니다 . 값은을 포함 할 수도 있습니다 =. 예를 들어 formula=5+3=8유효한 쿠키입니다.

/**
 * @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. 브라우저는 내림차순으로 쿠키를 공급하므로 역전은 객체에 가장 높은 우선 순위 쿠키가 표시되도록합니다. (이것은 .slice()배열의 돌연변이를 피하는 것입니다.)


설정 쿠키

"쓰기"쿠키는 Set-Cookie응답에 헤더를 사용하여 수행됩니다 . response.headers['Set-Cookie']객체는 실제로 배열입니다, 그래서 당신은 그것을 밀고됩니다. 문자열을 허용하지만 nameand 보다 더 많은 값을 갖습니다 value. 가장 어려운 부분은 문자열을 작성하는 것이지만 한 줄로 수행 할 수 있습니다.

/**
 * @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요청에 실제로 여러 헤더를 설정할 수 있으므로 여러 쿠키를 설정할 수 있습니다 . 그것이 배열 인 이유입니다.


외부 라이브러리에 대한 참고 사항 :

당신은을 사용하기로 결정한 경우 express, cookie-parser또는 cookie, 그들은 비 표준 기본값을 가지고 있습니다. 구문 분석 된 쿠키는 항상 URI 디코딩 (퍼센트 디코딩)됩니다. 즉, 다음 문자가 포함 된 이름 또는 값을 사용하는 경우 !#$%&'()*+/:<=>?@[]^`{|}해당 라이브러리에서 다르게 처리됩니다. 쿠키를 설정하는 경우 쿠키가로 인코딩됩니다 %{HEX}. 쿠키를 읽는다면 쿠키를 해독해야합니다.

예를 들어, email=name@domain.com쿠키는 유효한 쿠키이지만이 라이브러리는 쿠키를로 인코딩합니다 email=name%40domain.com. %쿠키를 사용하는 경우 디코딩에 문제가 발생할 수 있습니다 . 엉망이 될 것입니다. 예를 들어,이었다 쿠키는 : secretagentlevel=50%007and50%006이된다 secretagentlevel=507and506. 그것은 극단적 인 경우이지만 라이브러리를 전환 할 때주의해야 할 사항입니다.

또한 이러한 라이브러리에서 쿠키는 기본값으로 설정되어 path=/모든 URL 요청시 호스트로 전송됩니다.

당신이 인코딩을 원하거나이 값을 직접 디코딩하는 경우 사용할 수 있습니다 encodeURIComponent또는 decodeURIComponent각각.


참고 문헌 :


추가 정보:


0

먼저 쿠키를 만들어야합니다 (예 : 쿠키 안에 토큰을 래핑했습니다). 응답으로 설정하십시오. 다음과 같은 방법으로 쿠키를 사용하려면 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'속성을 호출하여 요청에서 쿠키를 추출해야합니다.

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()쿠키의 현재 목록을 얻기 위해 일부 cutesy 메소드 이름은? 요청의 두 가지 호출의 요점은 무엇입니까? 이것은 대부분 광고이며 답이 아닙니다.
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 Sorcery 및 RegEx Magic 사용

쿠키를 읽고 클라이언트 측의 키, 값 쌍의 객체로 전환하는 옵션은 서버 측에서도 사용할 수 있습니다.

참고 : 값이 있으면 =걱정할 필요가 없습니다. =열쇠 가 있으면 낙원에서 어려움을 겪습니다.

참고 사항 : 일부는 가독성을 주장 할 수 있으므로 원하는대로 분류하십시오.

내가 좋아하는 메모 : 오류 처리기 (시도 캐치)를 추가해도 아무런 문제가 없습니다.

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()쿠키를 ;( 공백 다음; )으로 나눕니다 .

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

그런 다음 정규 표현식 캡처 parens=사용하여 해당 배열을 매핑하고 분할합니다 .

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

그런 다음 친구`Object.fromEntries '를 사용하여 이것을 키, 발 쌍의 객체로 만듭니다.

누이 스.


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.