Using a HTTP Proxy Integration I want to access the cookies and add one to the json response. Is that possible?
-
Yes, that's definitely possible. You have access to all of the request parameters (headers, query string, path, body) and you can transform them using the mapping templates in your integration request to your HTTP backend. – Lorenzo d Feb 23 '16 at 19:50
2 Answers
To access cookies sent by the client in your backend you'll have to setup a mapping from the method request header to your integration request header.
These instructions assume you've already setup a simple method in API Gateway.
Access cookies in your backend
- Under Method Request, create an HTTP Request Header with the name of "Cookie"
- Under Integration Request, create an HTTP header with name "Cookie" and "Mapped from" value of
method.request.header.Cookie
. - You'll also likely need to setup CORS for this method. See: http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html
- Deploy your API and make a request to your API Gateway endpoint with your browser/client. You should see requests coming in to your HTTP backend with the Cookie header value sent from the browser.
Add cookie to response
You can setup a Set-Cookie
response header in an analogous fashion for the the integration response/method response side of the method configuration.
- Under Method Response, create a Response header with name
Set-Cookie
- Under Integration Response setup a Header Mapping with Response header
Set-Cookie
and Mapping valueintegration.response.header.Set-Cookie
Please note that at this time, API Gateway supports setting just a single Set-Cookie
response header. If your backend attempts to set multiple Set-Cookie headers, only the last one will be set. See this forum post for more details: https://forums.aws.amazon.com/thread.jspa?messageID=701434

- 2,016
- 10
- 17
-
Logically it should help and I do the same thing. However, what do I do, if API gateway in logs show that server does not return "Set-Cookie" header, even I am 100% sure that it does. Maybe you've faced same problem before? Any ideas? Thanks) – Sergey Potapov Mar 23 '16 at 17:05
-
@SergeyPotapov It'll not work if you are testing this on localhost because domains don't match. when you open the lambda's url itself it should work. If this is not the case you will have to validate your Method/Integration response – Glenn Van Schil Sep 27 '17 at 06:55
If you check the "Use Lambda Proxy integration" option in your API Gateway method, the request headers will be passed to your Lambda function via the event
variable. API Gateway will also expect a different response from your callback function. This response format can be use to dictate a Set-Cookie
header. e.g.:
callback(null, {
statusCode: 200,
headers: {'Set-Cookie': 'key=val'},
body: 'Some response'
});
This approach has the advantage of not requiring any Method Request or Method Response tweaks.
Here's a sample Lambda function using this logic to rotate a cookie value after each request.
exports.handler = (event, context, callback) => {
var cookies = getCookiesFromHeader(event.headers);
var old_cookie = cookies.flavor;
var new_cookie = pickCookieFlavor(old_cookie);
return callback(null, {
statusCode: 200,
headers: {
'Set-Cookie': setCookieString('flavor', new_cookie),
'Content-Type': 'text/plain'
},
body: 'Your cookie flavor was ' + old_cookie + '. Your new flavor is ' + new_cookie + '.'
});
};
/**
* Rotate the cookie flavor
*/
function pickCookieFlavor(cookie) {
switch (cookie) {
case 'peanut':
return 'chocolate';
case 'chocolate':
return 'raisin and oat';
default:
return 'peanut';
}
}
/**
* Receives an array of headers and extract the value from the cookie header
* @param {String} errors List of errors
* @return {Object}
*/
function getCookiesFromHeader(headers) {
if (headers === null || headers === undefined || headers.Cookie === undefined) {
return {};
}
// Split a cookie string in an array (Originally found http://stackoverflow.com/a/3409200/1427439)
var list = {},
rc = headers.Cookie;
rc && rc.split(';').forEach(function( cookie ) {
var parts = cookie.split('=');
var key = parts.shift().trim()
var value = decodeURI(parts.join('='));
if (key != '') {
list[key] = value
}
});
return list;
};
/**
* Build a string appropriate for a `Set-Cookie` header.
* @param {string} key Key-name for the cookie.
* @param {string} value Value to assign to the cookie.
* @param {object} options Optional parameter that can be use to define additional option for the cookie.
* ```
* {
* secure: boolean // Watever to output the secure flag. Defaults to true.
* httpOnly: boolean // Watever to ouput the HttpOnly flag. Defaults to true.
* domain: string // Domain to which the limit the cookie. Default to not being outputted.
* path: string // Path to which to limit the cookie. Defaults to '/'
* expires: UTC string or Date // When this cookie should expire. Default to not being outputted.
* maxAge: integer // Max age of the cookie in seconds. For compatibility with IE, this will be converted to a
* `expires` flag. If both the expires and maxAge flags are set, maxAge will be ignores. Default to not being
* outputted.
* }
* ```
* @return string
*/
function setCookieString(key, value, options) {
var defaults = {
secure: true,
httpOnly: true,
domain: false,
path: '/',
expires: false,
maxAge: false
}
if (typeof options == 'object') {
options = Object.assign({}, defaults, options);
} else {
options = defaults;
}
var cookie = key + '=' + value;
if (options.domain) {
cookie = cookie + '; domain=' + options.domain;
}
if (options.path) {
cookie = cookie + '; path=' + options.path;
}
if (!options.expires && options.maxAge) {
options.expires = new Date(new Date().getTime() + parseInt(options.maxAge) * 1000); // JS operate in Milli-seconds
}
if (typeof options.expires == "object" && typeof options.expires.toUTCString) {
options.expires = options.expires.toUTCString();
}
if (options.expires) {
cookie = cookie + '; expires=' + options.expires.toString();
}
if (options.secure) {
cookie = cookie + '; Secure';
}
if (options.httpOnly) {
cookie = cookie + '; HttpOnly';
}
return cookie;
}

- 971
- 1
- 11
- 28

- 2,019
- 23
- 29
-
-
4Can add one thing, I tried to get cookie from request in CloudFront(I use lambda as proxy). The actual value of cookies is actually stored in `event.Records[0].cf.request.headers.cookie[0].value` so one may need to slightly change function to find cookies. – Vyacheslav Tsivina Aug 20 '18 at 14:56