9

I need to access the raw body of a post request in Google App Script. I see there is something like

function doPost(request) {
  request.contentLength
}

that actually returns the right length of the raw content of the request body. So I thought there must be something to get the complete body, e.g. as a String.

I am not looking to access form field parameters that might be transferred using post.

Rubén
  • 34,714
  • 9
  • 70
  • 166
DJCordhose
  • 148
  • 1
  • 1
  • 5

8 Answers8

21

I know this question is old, but a lot of things have changed and Google has made this available now. You can easily access the body of a POST request from doPost(e) using:

e.postData.contents

If you want to parse incoming JSON, use this:

JSON.parse(e.postData.contents)
Sujay Phadke
  • 2,145
  • 1
  • 22
  • 41
  • yes but contents of postData does not contain the url of the post request. only the parameters. – mrtechmaker Apr 13 '17 at 12:18
  • @KaranAhuja what do you mean? The URL will point to your own published script. You know that anyways. Rest of the URL are the parameters, which you can now get. What's the problem? – Sujay Phadke Apr 14 '17 at 09:47
  • what if someone just copies my form action or $.ajax url and starts submitting junk data to my google script spreadsheet. So if i can restrict the google app script dopost function to only allow requests from my url and not any other url's then i can avoid spam. more discussion here - https://github.com/dwyl/html-form-send-email-via-google-script-without-server/issues/79 my username is karan-ta function doPost(e) { // How to get the url of the post request here ??? } – mrtechmaker Apr 14 '17 at 13:16
  • Well your published script URL is your "key". Of course if you share it or it is stolen, anyone can access it. But then so can anyone access your account if you lose your password. – Sujay Phadke Apr 14 '17 at 16:09
11

From the Release Notes of May 9, 2013, use request.postData.getDataAsString():

function doPost(request) {
    var jsonString = request.postData.getDataAsString();
    var jsonData = JSON.parse(jsonString);
    sheet.appendRow([ 'Data1:' , jsonData.Data1 ]); // Just an example
}
Rami Rosenbaum
  • 467
  • 5
  • 18
  • This will only work on single level JSON objects, e.g. {"test":1,"test2":2}. On multi-level JSON objects it throws a parse error. e.g {"test1":{"field1":1}} – Alex Egli Sep 21 '16 at 19:20
2

You can access the raw body of a post by creating a Blob from the parameter. You can then call various methods on the Blob object such as getBytes() or getDataAsString(). The functions are listed here.

function doPost(event) {
  var contentBlob = event.parameter.thefile;
  var contentAsString = contentBlob.getDataAsString();
  var bytes = contentBlob.getBytes();
  // do something with the contents ...
}
Kalyan Reddy
  • 1,132
  • 6
  • 5
  • Thaks for the pointer, but event.parameter seems to be empty if I do not supply a multi part form body, no? Note that I am not looking for a way to access a field in a multi part form post, but look for a way to process the full, raw post body content. – DJCordhose Oct 25 '12 at 22:05
  • Accessing an uploaded file is different from accessing the request body, and unfortunately I don't think it is currently possible to access the POST body. I also added an answer to this effect: http://stackoverflow.com/a/13715445/5295 – avernet Dec 05 '12 at 02:37
1

I don't think it is currently possible to access the POST body, say to implement a REST service. I submitted an enhancement request for this; if you stumbled upon this one, feel free to star it to vote on that issue.

avernet
  • 30,895
  • 44
  • 126
  • 163
1

This should also work.

function doPost(e) {

  if(typeof e !== 'undefined')
    Logger.log(e.parameter);

}
Amit Agarwal
  • 10,910
  • 1
  • 32
  • 43
0

The simplest way to find out all that you have access to is to print out the request object.

function doPost(request) {
  Logger.log(request); 
}

And then do a POST to your script's URL to see the log content

Srik
  • 7,907
  • 2
  • 20
  • 29
  • Thanks, for the hint, but all I see are the parameters and the contentLength: Logger.log([{queryString=null, parameter={}, contextPath=, parameters={}, contentLength=3}, []]) – DJCordhose Oct 18 '12 at 16:08
0

Depending on the nature of what you are trying do and what control you have over the origination of the post request, you may be able to integrate with the Drive API. If the post data can be sent to the user's Drive account as a file (containing raw JSON data for instance), your script could then locate that file, load it's content, do whatever you need with it (put it in a spreadsheet for example), and optionally trash the Drive file. This assumes, of course, that you have control over how the post request is sent. A workflow might involve:

  1. Client sends post request with data to user's Drive account (tag or name file to be easily identified later)
  2. Upon completion of Drive File creation, client sends a request to your script with parameter "method=consumeData" or such
  3. Your script checks the user's Drive account using the DocList service and retrieves any files uploaded for your script

I haven't tried this yet, but should work!

jwilkey
  • 326
  • 3
  • 11
0

This should work.

const doPost = (request) => {
  const { postData: { contents, type } = {} } = request;

  if (type === 'application/json') {
      //...
  }
  else {
    // console.error("Data is well not formatted. Check if that's JSON")
  }
  return ContentService.createTextOutput(JSON.stringify({ id: 1 })).setMimeType(ContentService.MimeType.JSON);

};