HTTP POST to Google Data API -- FM Crashes
This is a ridiculously amazing Plug-in. It bests any I have ever used by far. So many applications for it, so much power!
I am trying to do an HTTP POST to create events in Google Calendar and FileMaker crashes when I set the "Content-length: " header.
W/o the content-length header I get a 411 error for No Content-length.
How do I debug or error capture this?
I can run the HTTP POST with JavaScript just fine. I use XmlHttpRequest() right from the webviewer and all works just fine. That POST does not require any Content-length and I would think that I really don't need it.
Some potentially related background: Without including CURLOPT_CUSTOMREQUEST => "POST", Google reads the request as a GET rather than a POST. I read a bit about this on the Google API forums and include the CURLOPT_CUSTOMREQUEST => "POST". The same forums warned that Google will try to redirect PHP / CURL and that I need to set some CURLOPT to get Google to return the expected XML (unfortunately it didn't say how).
I realize this is not a Google API forum, but I am new to PHP and am really just looking for a tip or two on how to trace this error w/o crashing FileMaker.
Here is the function:
// Include error handler
$errorHandlerCode = fm_get_variable('__HTTP_errorHandlerCode');
eval($errorHandlerCode);
// Set variables from request
$url = fm_get_parameter('url');
$data = "\n"
. " \n"
. " Test 9 \n"
. " \n"
. " \n";
$auth = fm_get_parameter('auth');
$message = fm_get_parameter('message');
$timeout = (int)fm_get_parameter('timeout');
$header[] = "Authorization: GoogleLogin auth=".$auth ;
$header[] = "Content-type: application/atom+xml";
//$header[] = "Content-length: ".strlen($data);
// Get variables from memory
$proxyServer = fm_get_variable('__HTTP_proxyServer');
$authenticationType = fm_get_variable('__HTTP_authenticationType');
$userPassword = fm_get_variable('__HTTP_userPassword');
// Clear last info
$lastInfo = '';
fm_set_variable('__HTTP_lastInfo', $lastInfo);
// Branch for timeout (use default if a valid timeout is not supplied)
if (! is_int($timeout) || $timeout < 1) {
$timeout = 30;
}
// Branch for progress bar
if (! empty($message)) {
// Store current progress bar timeout setting (so it can be restored)
$originalPBTimeout = fm_progress_bar_timeout();
// Set progress bar timeout to be longer than request timeout so that it doesn't disappear early
fm_progress_bar_timeout($timeout + 120);
fm_new_progress_bar('pb1', 0, $message);
}
// Set https variables
$cert_file_path = FM_PHP_SUPPORT_PATH . 'ca-bundle.crt';
$ssl_verification = fm_get_variable('__HTTP_sslVerification') == 1 ? true : false;
// Branch for https (install cert file if necessary)
if (substr($url, 0, 5) == 'https') {
// If the cert file doesn't exist, attempt to install
if (! file_exists($cert_file_path)) {
// Get cert file
$cert_file_contents = file_get_contents('http://www.scodigo.com/downloads/smartpill/curl/ca-bundle.crt');
// Branch for error
if ($cert_file_contents == false) {
errorHandler(ERROR_SSL_CERT_NOT_DOWNLOADED);
}
// Install cert file
$cert_file_install = file_put_contents($cert_file_path, $cert_file_contents);
// Branch for error
if ($cert_file_install == false) {
errorHandler(ERROR_SSL_CERT_NOT_INSTALLED);
}
}
}
// Create a new curl resouce
$ch = curl_init();
// Set curl options
$options = array(
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $data,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_URL => $url,
CURLOPT_HEADER => false,
CURLOPT_HTTPHEADER => $header,
CURLOPT_CONNECTTIMEOUT => $timeout,
CURLOPT_FAILONERROR => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_VERBOSE => true,
CURLOPT_SSL_VERIFYPEER => $ssl_verification,
CURLOPT_SSL_VERIFYHOST => $ssl_verification,
CURLOPT_CAINFO => $cert_file_path
);
// Branch for proxy server
if (! empty($proxyServer)) {
$options[CURLOPT_HTTPPROXYTUNNEL] = true;
$options[CURLOPT_PROXY] = $proxyServer;
// Branch for proxy authentication
if (! empty($authenticationType)) {
$options[CURLOPT_PROXYAUTH] = $authenticationType;
$options[CURLOPT_PROXYUSERPWD] = $userPassword;
}
}
curl_setopt_array($ch, $options);
// Get the url
$response = curl_exec($ch);
// Branch for error
if ($response == false) {
// The curl error is sent as the additional description and we send die as false so that we can do some cleanup here before exiting
$result = errorHandler(ERROR_CURL_ERROR, "\nCurl said: " . curl_error($ch), false);
} else {
$result = $response;
// Build last info
$info = curl_getinfo($ch);
foreach($info as $key => $value) {
$lastInfo .= $key . ': ' . $value . "\n";
}
// If applicable, add proxy info
if (! empty($proxyServer)) {
$lastInfo .= 'proxy server: ' . $proxyServer . "\n";
if (! empty($authenticationType)) {
if ($authenticationType == CURLAUTH_NTLM) {
$lastInfo .= 'proxy authentication type: ' . "NTLM\n";
} else {
$lastInfo .= 'proxy authentication type: ' . "Basic\n";
}
$lastInfo .= 'proxy user name and password: ' . $userPassword . "\n";
}
}
// Store last info
fm_set_variable('__HTTP_lastInfo', $lastInfo);
}
// Close curl resource
curl_close($ch);
// Close progress bar if opened
if (! empty($message)) {
fm_close_progress_bar('pb1');
// Restore original timeout setting
fm_progress_bar_timeout($originalPBTimeout);
}
echo $result;
Still working?
Was curious if this is working and if it is where I could get some more information for getting it to work? Been beating my had against the wall all day until I stumbled onto this post.
Thanks for the help
Bob
Success from Command Line
Running CURL manually from the command line worked. This should be the exact same POST command that I am attempting to run from FileMaker:
curl --silent --request POST --data "@template_entry.xml" --header "Content-Type: application/atom+xml" --header "Authorization: GoogleLogin auth=DQAAAH8AAA...etc." "http://www.google.com/calendar/feeds/williambennett.tenor%40gmail.com/private/full/?gsessionid=qLP...etc." | tidy -xml -indent -quiet
Running that creates a google Calendar event based on the contents of the file @template_entry.xml. In my example, I used created the following Entry:
<entry xmlns='http://www.w3.org/2005/Atom' xmlns:gCal='http://schemas.google.com/gCal/2005' xmlns:gd='http://schemas.google.com/g/2005'><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2005#event' /><title type='text'>Velvet Singer2</title><content type='text' /><gd:when startTime='2009-04-11' endTime='2009-04-11' /></entry>
Thanks for any help!
Success from PHP!
I am all set. Thanks for the patience -- maybe someone else out there will go through the same thing.
Content-Length does NOT need to be set -- that was just a misleading error. In CURL, Google was spitting me back a URL with a session ID. Pop that URL into my PHP function and it just worked!
http://www.google.com/calendar/feeds/william....%40gmail.com/private/ful.......
Problem solved.
Success from PHP!
Hello Bill,
Glad to hear you got it figured out!
Also good to see that you created this as a PHPx function.
Regards,
Micah