我希望能够设置一个cookie,并在每次向nodejs服务器实例发出请求时读取该cookie。可以用几行代码完成,而不需要引入第三方库吗?
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。
答案 0 :(得分:178)
获取/设置cookie没有快速功能访问权限,因此我提出了以下黑客攻击:
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。
答案 1 :(得分:119)
如果您正在使用快速库,那么很多node.js开发人员都可以使用快速库。有关详细信息,请查看Express.js文档页面。
上面的解析示例有效,但express为您提供了一个很好的功能来处理:
app.use(express.cookieParser());
设置Cookie:
res.cookie('cookiename', 'cookievalue', { maxAge: 900000, httpOnly: true });
清除cookie:
res.clearCookie('cookiename');
答案 2 :(得分:25)
对于使用Express cookie parser的建议,RevNoah得到了最好的答案。但是,这个答案现在已经过了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等更多操作
答案 3 :(得分:10)
您可以使用“cookies”npm模块,该模块具有一整套功能。
答案 4 :(得分:6)
Cookie被转移through HTTP-Headers
您只需要解析请求标头并放置响应标头。
答案 5 :(得分:6)
要使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']
答案 6 :(得分:5)
作为@Corey Hart答案的增强,我使用以下方式重写parseCookies()
:
以下是工作示例:
var http = require('http');
function parseCookies(cookie) {
return cookie.split(';').reduce(
function(prev, curr) {
var m = / *([^=]+)=(.*)/.exec(curr);
var key = m[1];
var value = decodeURIComponent(m[2]);
prev[key] = value;
return prev;
},
{ }
);
}
function stringifyCookies(cookies) {
var list = [ ];
for (var key in cookies) {
list.push(key + '=' + encodeURIComponent(cookies[key]));
}
return list.join('; ');
}
http.createServer(function (request, response) {
var 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);
答案 7 :(得分:2)
这是一个简洁的复制粘贴补丁,用于管理节点中的cookie。为了美丽,我将在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
答案 8 :(得分:2)
让我重复这部分问题,而这里的答案却被忽略了:
是否可以通过几行代码来完成,而无需引入第三方库?
从带有Cookie
标头的请求中读取Cookie。它们仅包含name
和value
。由于路径的工作方式,可以发送多个相同名称的cookie。在NodeJS中,所有Cookie均以一个字符串的形式发送到Cookie
标头中。您用;
分割了它们。拥有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()
是为了避免数组发生突变。)
Set-Cookie
标头来完成“编写” cookie。 response.headers['Set-Cookie']
对象实际上是一个数组,因此您将使用它。它接受一个字符串,但具有更多的值,而不仅仅是name
和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);
请记住,您可以设置多个Cookie,因为实际上您可以在请求中设置多个Set-Cookie
标头。这就是为什么它是一个数组。
如果您决定使用express
,cookie-parser
或cookie
,请注意它们具有非标准的默认值。解析的Cookie始终为URI解码(百分比解码)。这意味着如果您使用具有以下任何字符的名称或值:!#$%&'()*+/:<=>?@[]^`{|}
,这些库将对它们进行不同的处理。如果您要设置cookie,它们将使用%{HEX}
进行编码。而且,如果您要读取Cookie,则必须对其进行解码。
例如,尽管email=name@domain.com
是有效的cookie,但是这些库会将其编码为email=name%40domain.com
。如果您在Cookie中使用%
,则解码可能会出现问题。它会被扭曲。例如,您的Cookie:secretagentlevel=50%007and50%006
变为secretagentlevel=507and506
。这是一个极端的情况,但是在切换库时要注意一些事情。
此外,在这些库上,cookie设置为默认的path=/
,这意味着它们会在每个url请求上发送到主机。
如果您想自己对这些值进行编码或解码,则可以分别使用encodeURIComponent
或decodeURIComponent
。
参考:
其他信息:
答案 9 :(得分:1)
如果您不关心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
});
});
答案 10 :(得分:0)
这里有一个选项,可以读取cookie并将其变成Key对象,即客户端的“值对”,也可以在服务器端使用。
注意 :如果值中有=
,请放心。如果密钥中有=
,那么天堂就麻烦了。
更多注释 :有些人可能会争辩可读性,因此请根据需要对其进行分解。
我喜欢的笔记 :添加错误处理程序(尝试捕获)不会有问题。
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"]
然后,我们映射该数组并使用regex capturing parens按=
的第一次出现进行拆分:
[["name", "Cookie Monster"], ["likesCookies", "yes=withARandomEquals"]]
然后使用我们的朋友`Object.fromEntries使其成为键,val对的对象。
新手。
答案 11 :(得分:0)
我写了这个简单的函数
req.headers.cookie
和 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
}
答案 12 :(得分:-1)
要获得单个Cookie ,此代码将比解析所有Cookie更快:
getSingleCookie = (cookie, name) ->
vIx = cookie.indexOf "#{name}="
if vIx != -1
egalIx = vIx+name.length+1
colIx = cookie.indexOf ';', egalIx
v = if colIx == -1
cookie.substring egalIx
else
cookie.substring egalIx, colIx
return v
应该像:
getSingleCookie request.headers, 'my_cookie'
答案 13 :(得分:-1)
首先需要创建cookie(我在cookie中包装了令牌作为示例),然后将其设置为响应。以下面的方式使用cookie安装cookieParser
app.use(cookieParser());
浏览器会将其保存在“资源”标签中,然后将其用作以初始网址为基础的每个请求
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