NetSuite: Working With Cookies in Suitelets

Published on November 30, 2022.

One of the projects that I've been working on is a Web portal for a NetSuite client. The portal is built on the NetSuite platform as a Suitelet. It uses a customized and enhanced version of my SuiteFrame framework, and is being served up behind NGINX (using this technique that I shared back in January).

While developing the portal, I needed to add support for sessions. I'll write about how I'm managing sessions in a future post.

One of the things that I needed for session management was a way to work with cookies. In this post, I'll share some of the code that I wrote to do that.

Getting Cookies

When using a Suitelet, we have access to all of a request's headers, and can get to them via context.request.headers. Here's a sample of what the headers look like:

{
     "X-Akamai-SR-Hop": "1",
     "true-client-ip": "83.74.96.100",
     "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.6.1 Safari/605.1.15",
     "x-forwarded-port": "443",
     "x-advpf-parse-category": "DEFAULT_ALLHTML",
     "Accept-Encoding": "gzip",
     "True-Client-IP": "83.74.96.100",
     "via": "1.1 v1-akamaitech.net(ghost) (AkamaiGHost), 1.1 akamai.net(ghost) (AkamaiGHost)",
     "x-forwarded-host": "9999999-sb3.extforms.netsuite.com:443, 9999999-sb3.extforms.netsuite.com",
     "host": "9999999-sb3.extforms.netsuite.com",
     "X-Advpf-Parse-Category": "DEFAULT_ALLHTML",
     "ns-client-ip": "83.74.96.100",
     "connection": "keep-alive",
     "cache-control": "no-cache, max-age=0",
     "X-Real-IP": "55.140.23.28",
     "Cookie": "sessionID=20170094-2961ae54-de92-49ac-a0a8-93f13786fede; NS_ROUTING_VERSION=LAGGING; c7tXy98SOdcsRmaJORP2xg=AAABhHfmy1MPCnHzorzdLrEhYIuHIuNVNakHqWKIjIhEl5W8hlAI5A",
     "NS-Client-IP": "83.74.96.100",
     "Akamai-Origin-Hop": "2",
     "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
     "cookie": "sessionID=20170094-2961ae54-de92-49ac-a0a8-93f13786fede; NS_ROUTING_VERSION=LAGGING; c7tXy98SOdcsRmaJORP2xg=AAABhHfmy1MPCnHzorzdLrEhYIuHIuNVNakHqWKIjIhEl5W8hlAI5A",
     "x-forwarded-proto": "https",
     "accept-language": "en-US,en;q=0.9",
     "X-Forwarded-Proto": "https",
     "X-Forwarded-Host": "9999999-sb3.extforms.netsuite.com:443, 9999999-sb3.extforms.netsuite.com",
     "Akamai-GRN": "0.4f6adc17.1669841763.d8873b13, 0.378cd017.1669841763.4e34b9ba",
     "Connection": "keep-alive",
     "Host": "9999999-sb3.extforms.netsuite.com",
     "Pragma": "no-cache",
     "x-forwarded-for": "83.74.96.100, 23.220.106.79, 55.140.23.28, 10.136.0.13",
     "X-Forwarded-Port": "443",
     "akamai-origin-hop": "2",
     "pragma": "no-cache",
     "Via": "1.1 v1-akamaitech.net(ghost) (AkamaiGHost), 1.1 akamai.net(ghost) (AkamaiGHost)",
     "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
     "x-real-ip": "55.140.23.28",
     "x-akamai-sr-hop": "1",
     "X-Akamai-CONFIG-LOG-DETAIL": "true",
     "x-akamai-config-log-detail": "true",
     "x-forwarded-server": "forms.na7.netsuite.com",
     "Cache-Control": "no-cache, max-age=0",
     "X-Forwarded-For": "83.74.96.100, 23.220.106.79, 55.140.23.28, 10.136.0.13",
     "Accept-Language": "en-US,en;q=0.9",
     "X-Forwarded-Server": "forms.na7.netsuite.com",
     "accept-encoding": "gzip",
     "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.2.35 (KHTML, like Gecko) Version/15.16.1 Safari/605.2.35",
     "akamai-grn": "0.4f6adc17.1669841763.d8873b13, 0.327cd017.1669841763.4e34b9ba"
}

Each header is listed twice, once with header name in lower case, and a second time in intercaps. I usually refer to the lower case versions, but I don't think it matters all that much.

Cookies are available via the "cookie" header. It looks like this:

"cookie": "sessionID=20170094-2961ae54-de92-49ac-a0a8-93f13786fede; NS_ROUTING_VERSION=LAGGING; c7tXy98SOdcsRmaJORP2xg=AAABhHfmy1MPCnHzorzdLrEhYIuHIuNVNakHqWKIjIhEl5W8hlAI5A"

So we can reference it using context.request.headers['cookie']. That's easy enough. But that returns the entire cookie string value. To parse it, I wrote this function, which takes the script context, gets the cookie header, parses it, and returns it as an object.

function cookiesGet( context ) {
			
	var cookies = {}
	
	var cookiesOriginal = context.request.headers['cookie'];
	
	if ( cookiesOriginal == null ) {
		return cookies;
	}			
	
	cookiesOriginal = cookiesOriginal.split("; ");	    							
	
	for ( var i = 0; i < cookiesOriginal.length; i++ ){	    		
	
		var thisCookie = cookiesOriginal[i];
		
		thisCookie = thisCookie.split("=");	 
		
		cookies[thisCookie[0]] = thisCookie[1];
		
	}
	
	return cookies;
	
}	

The result will look something like this:

{
     "sessionID": "20170094-2961ae54-de92-49ac-a0a8-93f13786fede",
     "NS_ROUTING_VERSION": "LAGGING",
     "c7tXy98SOdcsRmaJORP2xg": "AAABhHfmy1MPCnHzorzdLrEhYIuHIuNVNakHqWKIjIhEl5W8hlAI5A"
}

Setting Cookies

To set cookies in a Suitelet, we can use the context.response.setHeader method. For example, to drop a cookie with name-value pair "a=1" you would use something like this:

context.response.setHeader( { name: 'Set-Cookie', value: 'a=1; path=/' } );

Dropping multiple name-value pairs can be tricky. For example, to set a second name-value pair ("b=2") you might try this...

context.response.setHeader( { name: 'Set-Cookie', value: 'a=1; b=2; path=/' } );

But the resulting cookie will only include the first name-value pair, and ignore the second.

Calling the setHeader method twice, like this...

context.response.setHeader( { name: 'Set-Cookie', value: 'a=1; path=/' } );
context.response.setHeader( { name: 'Set-Cookie', value: 'b=2; path=/' } );

... will result in a cookie that includes only the second name-value pair.

One method that I've found to solve this issue is to put the values in an object, JSON-encode the object, and then URL-encode the JSON string. For example...

let values = {a: 1, b: 2}
values = JSON.stringify(values);
values = encodeURIComponent(values);
context.response.setHeader( { name: 'Set-Cookie', value: `values=${values}; path=/` } );

You would then read the cookie, and decode it. For example...

let cookies = cookiesGet( context );
let values = cookies.values;
values = decodeURIComponent(values);
values = JSON.parse( values );

Wrapping Up

I hope you find this short post to be helpful.

Happy SuiteScripting!

About Me

Hello, I'm Tim Dietrich. I develop custom software for businesses that are running on NetSuite, including mobile apps, Web portals, Web APIs, and more.

I'm the developer of several popular NetSuite open source solutions, including the SuiteQL Query Tool, SuiteAPI, and more.

I founded SuiteStep, a NetSuite development studio, to provide custom software and AI solutions - and continue pushing the boundaries of what's possible on the NetSuite platform.

Copyright © 2025 Tim Dietrich.