How to Handle GET and POST HTTP Requests in Google Apps Script
With Google Apps Script, you can easily create a Web App that serves HTML, JSON, XML or plain text output using the HTML service. When your publish your Google Script project as a web app, the script gets a public URL (think API) that can be invoked from external applications using either HTTP GET or POST requests with query parameters and request body.
When publishing the script as a web app, make sure to choose “Allow anonymous access” and execute the script as yourself. If you edit the script, create a new version inside the script editor and deploy the latest version.
Here are some examples that demonstrate how you can convert your Google Script into a web API by adding the doGet
and doPost
methods to your project.
Handling GET Requests
When a script is published as a web app, the doGet
callback function handles all GET requests made to the script’s public URL. The Google Script can return plain text content, HTML or JSON data as shown in the examples below:
Return Text Content
const doGet = (event = {}) => {
const { parameter } = event;
const { name = 'Anonymous', country = 'Unknown' } = parameter;
const output = `Hello ${name} from ${country}`;
return ContentService.createTextOutput(output);
};
Any query parameters added to the Google Script URL, like name and country in our example, become available in the parameter
property of the event
object of the doGet and doPost methods in Apps Script.
https://script.google.com/macros/s/12345/exec?name=Amit&country=India
If something is not working, you can always log the request object to the StackDrive console logs and easily debug the full request.
console.log(`doGet`, JSON.stringify(event));
Serve JSON Output
The same ContentService can be used to return JSON output by using the setMimeType
method with the mime set as ContentService.MimeType.JSON
.
const doGet = (event = {}) => {
const { parameter } = event;
const { name = 'Anonymous', country = 'Unknown' } = parameter;
const message = `Hello ${name} from ${country}`;
const json = { name, country, message };
return ContentService.createTextOutput(JSON.stringify(json)).setMimeType(ContentService.MimeType.JSON);
};
When testing HTTP requests in Google Script with utilities like CURL or Postman, ensure that that “Automatically follow redirects Follow HTTP 3xx responses as redirects” setting is turned on since the ContentService serves a 301 redirect from the script.googleusercontent.com
domain.
Serving HTML Content
Your Google Apps script project can serve HTML web pages with the HtmlService
service. The web pages served with App Script included Google warning header at the top but it can be removed if you embed the Google Script in another web page (like Google Sites) with the IFRAME tag.
const doGet = (event = {}) => {
const { parameter } = event;
const { name = 'Anonymous', color = 'Black' } = parameter;
const html = `<p><b>${name}'s</b> favorite color is <font color="${color}">${color}</font></p>`;
return HtmlService.createHtmlOutput(html)
.setTitle('Apps Script Webpage')
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
};
You should set the X-Frame-Options
header of the webpage to XFrameOptionsMode.ALLOWALL
to allow other pages to embed your Google Script HTML page.
Handle POST Requests with Google Scripts
The callback function doPost
is invoked when an HTTP POST request is make to your Google Script URL that is published as a web app with anonymous access.
const doPost = (request) => {
console.log(request);
return ContentService.crateTextOutput(JSON.stringify(request));
};
The request
argument of the doPost method can include:
queryString
- The name-value pairs sent in the URL of the request (name=Mike&age=12)parameter
- The query string name-value pairs are also accessible inside the parameter object similar to GET requests (e.paremeter.name or e.parameter.age).postData
- The contents property of the postData object includes the POST body and type property of postData specifies the MIME type of the post body. It can have values likeapplication/x-www-form-urlencoded
(key-value pairs separated by the ’&’ character and each key is separated from its encoded value by ’=’),application/json
for JSON data ortext/plain
for text body.
For binary data, like file uploads, the HTTP post request is sent with the multipart/form-data
mime type. In the case of application/x-www-form-urlencoded
, the queryString is set as part of the POST request body.
const doPost = (request = {}) => {
const { parameter, postData: { contents, type } = {} } = request;
const { source } = parameter;
if (type === 'application/json') {
const jsonData = JSON.parse(contents);
return ContentService.createTextOutput(JSON.stringify(jsonData));
}
if (type === 'application/x-www-form-urlencoded') {
const json = {};
contents
.split('&')
.map((input) => input.split('='))
.forEach(([key, value]) => {
json[decodeURIComponent(key)] = decodeURIComponent(value);
});
return ContentService.createTextOutput(JSON.stringify(json));
}
return ContentService.createTextOutput(contents);
};
Testing HTTP Requests with Google Scripts
You can use Postman, RequestBin, CURL or any of your favorite dev tool to send GET and POST requests to your Apps Script service. We’ll use Apps Script itself with the built-in UrlFetchApp service to test the request and response.
Working with HTTP GET Requests
In this example, the GET API coverts the query string to JSON. The test function makeHttpGetRequest
compares the supplied query string value with the returned object.
const doGet = (event = {}) => {
const { parameter } = event;
const { name, country } = parameter;
return ContentService.createTextOutput(JSON.stringify({ name, country })).setMimeType(ContentService.MimeType.JSON);
};
const makeHttpGetRequest = () => {
const queryString = '?name=Amit+Agarwal&country=India';
const apiUrl = ScriptApp.getService().getUrl();
const url = apiUrl + queryString;
const options = {
method: 'GET',
followRedirects: true,
muteHttpExceptions: true,
contentType: 'application/json',
};
const response = UrlFetchApp.fetch(url, options);
if (response.getResponseCode() == 200) {
const { country } = JSON.parse(response);
Logger.log('Country', country);
}
};
Working with HTTP GET Requests
The doPost method returns either the country or the name from the request body depending on the action parameter of the script URL.
const doPost = (request = {}) => {
const { parameter, postData: { contents, type } = {} } = request;
const { name, country } = JSON.parse(contents);
if (parameter.action === 'getCountry') {
return ContentService.createTextOutput(country);
} else {
return ContentService.createTextOutput(name);
}
};
const makeHttpPostRequest = () => {
const url = ScriptApp.getService().getUrl() + '?action=getCountrdy';
const payload = {
name: 'Amit Agarwal',
blog: 'www.labnol.org',
country: 'India',
};
const options = {
method: 'POST',
followRedirects: true,
muteHttpExceptions: true,
payload: JSON.stringify(payload),
};
const response = UrlFetchApp.fetch(url, options);
if (response.getResponseCode() == 200) {
Logger.log(response.getContentText());
}
};
POST Request with HTML Forms
The next example uses a simple HTML form that sends a POST request with application/x-www-form-urlencoded
mime type.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
</head>
<body>
<form action="https://script.google.com/macros/s/#####/exec" method="POST" target="_blank">
<input type="text" name="name" />
<input type="text" name="country" />
<button type="submit">Submit</button>
</form>
</body>
</html>
The POST method returns the POST body of the request.
const doPost = (request = {}) => {
const { postData: { contents, type } = {} } = request;
return ContentService.createTextOutput(contents);
};
Using CURL to make HTTP Requests
The POST API returns a parameter from the query string of the URL and the name from the request body.
const doPost = (request = {}) => {
const { parameter, postData: { contents, type } = {} } = request;
const data = JSON.parse(contents);
return ContentService.createTextOutput(parameter.secret + type + data.name);
};
You can use CURL to make a POST request to Google Script. Remember to add the -L flag so that curl follows the redirect from script.google.com to googleusercontent.com.
curl -L \
-H 'Content-Type:application/json' \
-d '{"name": "Amit","country": "India"}' \
"https://script.google.com/macros/s/###/exec?secret=1234"
Also see: AJAX, jQuery and Google Scripts
Amit Agarwal
Google Developer Expert, Google Cloud Champion
Amit Agarwal is a Google Developer Expert in Google Workspace and Google Apps Script. He holds an engineering degree in Computer Science (I.I.T.) and is the first professional blogger in India.
Amit has developed several popular Google add-ons including Mail Merge for Gmail and Document Studio. Read more on Lifehacker and YourStory