1

I'm trying to do the bare minimum, just to get it working.

Here is my Google Script:

function doPost(e) {
  return ContentService.createTextOutput(JSON.stringify(e.parameter));
}

Here is my PHP code:

$url = 'https://script.google.com/a/somedomain.com/macros/s/### script id ###/exec';
$data['name'] = "Joe";
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-type: multipart/form-data"));
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
// curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$result = curl_exec($ch);
$error  = curl_error($ch);

Executing this, $result is true.

If I uncomment the CURLOPT_RETURNTRANSFER line, $result =

<HTML>
<HEAD>
<TITLE>Bad Request</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<H1>Bad Request</H1>
<H2>Error 400</H2>
</BODY>
</HTML>

$error is always empty.

I would use doGet() but I need to send some rather large POSTs that will exceed what GET can handle.

How can I post to a Google script and return data?

------ UPDATE ------

I've just learned my lead developer tried this some time ago and concluded doPost() errors when returning so apparently it's not just me. My take is that Google is simply not reliable enough to use. I would love for someone to prove me wrong.

------ UPDATE 2 - THE FIX ---------

Apparently this was the problem:

curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));

needs to be:

curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

No idea why http_build_query() caused it to error.

Tim Duncklee
  • 1,420
  • 1
  • 23
  • 35
  • My guess would be the `curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-type: multipart/form-data"));` was the culprit. This should not have been needed. CURL would put the proper type the header itself based on the post data being a query string or an array. It may work with the query string without this header option. – Misunderstood Nov 19 '17 at 20:55
  • When a query string is used the header should be: `application/x-www-form-urlencoded ` When an array the header should be: `multipart/form-data` – Misunderstood Nov 19 '17 at 21:07

2 Answers2

3

Try reading the documentation for CURLOPT_POSTFIELDS and you'll see that is says To post a file, prepend a filename with @ and use the full path. That looks what you are trying to do. Note that in php 5.5, the CURLFile class was introduced to let you post files.

If you are using php 5.5 or later, you might try this:

$url = 'https://script.google.com/a/somedomain.com/macros/s/### script id ###/exec';

// create a CURLFile object:
$cfile = new CURLFile('file.pdf','application/pdf'); // you can also optionally use a third parameter

// your POST data...you may need to add other data here like api keys and stuff
$data = array("fileName" => $cfile);

$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-type: multipart/form-data"));
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);

// FROM THE DOCS:
// If value is an array, the Content-Type header will be set to multipart/form-data (so you might skip the line above)
// As of PHP 5.2.0, value must be an array if files are passed to this option with the @ prefix
// As of PHP 5.5.0, the @ prefix is deprecated and files can be sent using CURLFile
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

// set this to TRUE if you want curl_exec to retrieve the result
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$result = curl_exec($ch);
if ($result === FALSE) {
    echo "The result is FALSE. There was a problem\n";
    $error  = curl_error($ch);
    var_dump($error);
    die();
} else {
    echo "success!\n";
    var_dump($result);
}

// this can give you more information about your request
$info = curl_getinfo($ch);
if ($info === FALSE) {
    echo "curlinfo is FALSE! Something weird happened";
}
var_dump($info); // examine this output for clues

EDIT: If you are not getting any error, and $result comes back with something like "Bad Request" then you will need to inspect the result more closely to find out what the problem is. A well-behaved API should have informative information to help you fix the problem. If the API doesn't tell you what you did wrong, you can examine the curlinfo you get from these commands:

$info = curl_getinfo($ch);
var_dump($info); // examine this output for clues

if $result and $info don't tell you what you've done wrong, try reading the API documentation more closely. You might find a clue in there somewhere.

If you can't figure out what the problem is using these tactics, there's not much else you can do with your code. You'll need more information from the maintainers of the API.

S. Imp
  • 2,833
  • 11
  • 24
  • Sorry for the confusion. I'm not trying to post a file. Just text. I've updated the question for clarity. – Tim Duncklee Nov 19 '17 at 01:49
  • 1
    @TimDuncklee I edited my post to provide a little more info. Unfortunately there's not much else you can do beyond what I've posted here. If you are getting "Bad Request" then you need to find out from the API or the API docs what you are doing wrong. – S. Imp Nov 19 '17 at 01:58
  • curl_getinfo($ch) returns nothing. I think Google is simply not reliable enough to use. It is random but I can sometimes do the same with a doGET() but often it returns an error also. Run the exact same code a while later with NO changes to the code and it works. What I'm trying to do is trivial and I've done this many times outside of Google. It should not be this difficult. – Tim Duncklee Nov 19 '17 at 02:19
  • that's pretty weird that curl_getinfo returns *nothing.* Do you mean FALSE, the empty string, zero, or NULL? – S. Imp Nov 19 '17 at 03:16
  • curl_getinfo returns null with and without CURLOPT_RETURNTRANSFER set. I do believe this is a google bug. With CURLOPT_RETURNTRANSFER set curl_exec() returns html with the Bad Request in

    tags so I think curl is succeeding. It's Google sending the error.

    – Tim Duncklee Nov 19 '17 at 03:23
  • 1
    @TimDuncklee Not likely it's a Google error. Most likely there is something wrong with passed parameters based on the returned bad request message. – Misunderstood Nov 19 '17 at 12:03
  • Try reading the entire text of the Bad Request response and you may actually find a useful error message. – S. Imp Nov 19 '17 at 18:31
  • Also, I find it really hard to believe that curl_getinfo returns NULL if you are using it correctly. You should be calling this function *after* you call curl_exec. – S. Imp Nov 19 '17 at 18:31
  • @S. Imp I have pasted the entire error message in my question. I am calling curl_getinfo($ch); immediately after curl_exec($ch); – Tim Duncklee Nov 19 '17 at 19:28
  • @TimDuncklee I see from your updates that you never actually tried my code because I had removed the http_build_query bit. I also see from the response code that you posted that the response says it returned a response code of 400. I find it puzzling that curl_getinfo would return NULL in this case, but haven't seen the exact code (or exact url) that you are calling. – S. Imp Nov 19 '17 at 22:39
  • 1
    @S. Imp I did not try your code because I was not trying to upload a file. curl_getinfo was returning valid info. It was my fault. I did not notice I was overwriting the returned value by the time I hit my breakpoint. Thank you for your help! – Tim Duncklee Nov 19 '17 at 22:56
1

You need to look at your HTTP Request header to see what is actually being posted.

When trouble shooting I add these options:

curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_TIMEOUT,10);
curl_setopt($ch, CURLOPT_FAILONERROR,true);
curl_setopt($ch, CURLOPT_ENCODING,"");

curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);

CURLINFO_HEADER_OUT will add "request_header" to curl_getinfo()

You also want to look at these curl_getinfo() elements.

  • request_size
  • size_upload
  • upload_content_length
  • request_header
Misunderstood
  • 5,534
  • 1
  • 18
  • 25