Empty response from push notification - google-drive-api

I'm getting empty response posts from google drive push notification api. I'm not sure if I'm not looking correctly at the posted data to my listening app or if I'm incorrectly setting up my channels.
I've able to setup channels verified with the responses like:
[14-07-26 14:27:19:697 EDT] {
"kind": "api#channel",
"id": "ce976221-7f6c-44bd-82f3-6a7a539fbc18",
"resourceId": "YTWyD_gD_mUUBM8Ttrqc6P6ZCxI",
"resourceUri": "https://www.googleapis.com/drive/v2/files/1T0GX4lBx6yH2DHMAS624qk5bQylZm1kRs_rE8tIHS_c?updateViewedDate=false&alt=json",
"token": "caller=https://script.google.com/a/macros/ccsknights.org/s/AKfycbxc0JwGl-TptxgsHhWPaAZbIgQXRk7fhB282ReOa09f_6HmGPkw/exec",
"expiration": "1406402836000"
}
And my listening app does receive notifications as I mess with the test document. I do a dump of the entire posted data but it shows up as:
{queryString=null, parameter={}, contextPath=, parameters={}, contentLength=0}
I've posted other data to the app to test it and it shows up as expected:
{queryString=bob/asdasd/asdasdsd/adsad, postData=FileUpload, parameter={test=yes, test2=no, bob/asdasd/asdasdsd/adsad=}, contextPath=, parameters={test=[Ljava.lang.Object;#2fc540bd, test2=[Ljava.lang.Object;#3f1d50cb, bob/asdasd/asdasdsd/adsad=[Ljava.lang.Object;#1da35fcc}, contentLength=17}
The listening app is simply:
var sslog = SpreadsheetApp.openById('1dOic6cWtTuj7lxi-QoRK2hrlXArd2C5ZlqOEmCvJ6R0').getSheets()[0];
function doPost(e) {
sslog.appendRow([e]);
return 200;
//return ContentService.createTextOutput().setContent(JSON.stringify(e)).setMimeType(ContentService.Mi meType.JSON);
}
Is there something I'm missing to be able to extract the push notification data from the post?

The correct answer is the post body is retrieved in the postData object. It was added but not documented. You can find more about it at: https://developers.google.com/apps-script/releases/2013
function doPost(e) {
Logger.log(e.postData.getDataAsString());
}

If you are watching a File resource, POST body is always empty. All of the information that's available to you is contained in "X-Goog-*" headers.

Related

Postman: POST request of nested JSON via form-data not working (while via raw-data ok)

I want to POST the following JSON-object via Postman:
{
"title": "test_title",
"date": "2021-12-31",
"attachments": [
{
"name": "test_attachment"
}
]
}
This works perfectly fine, when using Postman's raw input form for the request-body: I get a "201 Created"-response back.
However, when using the form-data to POST the data, I get the error "Invalid data. Expected a dictionary, but got str." (see also screenshot below) What am I doing wrong here? I tried all kind of other versions to enter the attachment-key:value pair but nothing worked so far
I managed to make it work! (note: I added some additional fields compared to the screenshot in question. See below for details:
You did nothing wrong.
If you want to make a request with json object, then you go with raw type (json) in postman.
If you want to upload file, then you use form-data
One more thing, status 201 means the request is succeed, your object has been created.
var express = require('express')
const multer = require('multer')
const upload = multer()
var app = express()
app.use(express.json());
app.post('/test',upload.none(), function (req, res, next) {
res.send(req.body)
})
app.listen(80, function () {
console.log('web server listening on port 80')
})
Above is a sample endpoint which works with both form-data and json , just do a post to http://localhost:80/test with both form data and raw json
you can see both will get parsed correclty
APIs are just abstraction , its like a function that takes in many attribute, how you parse it depends on the implementation ( how the api function is written) .
so answer is "Talk to the developer" on how the API is implemented and what it is supporting
I'm having issue in placing json into form format the way Daniel did in Postman. Need help in figuring out what is it required to place the cascaded json objects into form data format. Please see here that I'm trying to accomplish.
JSON Format (to be filled into Postman form-data section:
{
"primary_object": {
"child_object_1": [{"id": 12345678, "value": "abc"},{"id": 87654321, "value": "xyz"}],
"child_object_2": [
"first_val",
"second_val"
]
}
}

Why am I getting an empty response back from UrlFetchApp in Google Apps Script?

I am trying to make a GET request to an external API from a Google Apps Script using UrlFetchApp. When I make this request with Postman or curl, I get back the expected response. However, when I try it with UrlFetchApp, I get back an empty response, {}.
I have tried using Basic Auth and OAuth 2, as well as explicitly setting the oauthScopes property in the manifest as described here.
I have confirmed with the API team that they are indeed sending back a full response when I hit the endpoint, but all I receive is {}. My problem seems similar to this StackOverflow question which went unanswered.
var headers = {
"X-Client-Key": "KEY",
"Authorization": "Bearer TOKEN"
};
var options = {
method: "get",
headers: headers,
}
var response = UrlFetchApp.fetch(ENDPOINT, options);
console.log(JSON.stringify(response)); // returns {}
Do not take what you see in logs at face value. fetch method of the UrlFetchApp service always returns an instance of HTTPResponse which is an object first and foremost. This is what the logs show you (I am assuming you are logging the response because this is the only context I am aware of where {} is displayed).
To extract useful information from the response, use the appropriate methods exposed on HTTPResponse instances, like getResponseCode or getContentText.

How to determine why an Azure Function App is not triggered by a webhook

I have:
An JavaScript Azure Function in an HTTP webhook configuration; the Function provides a URL; the Function performs an action
A webhook configured in the software I hope to receive notifications from
An Azure Logic App with an HTTP/webhook step that provides a URL for the webhook notification to go to
My goal is that the Azure Function's URL receives notifications from the software's webhook and performs an action. The Azure Logic App is for testing only.
What works
When the the Azure Logic App's URL is used in the software's webhook configuration, the desired action is performed. All works as expected.
The Azure Logic App's logging shows the JSON output from the incoming webhook. I expect (but believe this may be where I am going wrong) that this is the JSON the webhook is sending to the Azure Logic App's URL. When this JSON is used in the Azure Function UI's "Test" tab > "Request body" field, the desired action is performed. All works as expected.
When the Azure Function's URL and the JSON is in a Postman request, the desired action is performed. All works as expected.
What doesn't work
When the Azure Function's URL is used in the software's webhook configuration, no action is performed. This is of course my goal. From everything I have read, I understand that this URL as a webhook endpoint should work.
Azure Function's URL
This is from Get function URL > default (Function key).
https://<app_name>.azurewebsites.net/api/content?code=<api_key>
Other Azure Function config settings
Allowed HTTP methods: GET, POST
Authorization level: Function
The JSON I believe to be coming over the webhook
{
"headers": {
"Expect": "100-continue",
"Host": "redacted",
"X-Telligent-Webhook-Sender": "redacted",
"Content-Length": "16908",
"Content-Type": "application/json; charset=utf-8"
},
"body": {
"events": [{
"TypeId": "ec9da4f4-0703-4029-b01e-7ca9c9ed6c85",
"DateOccurred": "2018-12-17T22:55:37.7846546Z",
"EventData": {
"ActorUserId": 9999,
"ContentId": "redacted",
"ContentTypeId": "redacted",
"ForumReplyId": 9999,
"ForumThreadId": 9999,
"ForumId": 9999
}
}]
}
}
I also tried with the following test code for the same results. It aligns more closely with the sample payload data provided by the software company:
What I tried
{
"events": [{
"TypeId": "ec9da4f4-0703-4029-b01e-7ca9c9ed6c85",
"DateOccurred": "2018-12-17T22:55:37.7846546Z",
"EventData": {
"ActorUserId": 9999,
"ContentId": "redacted",
"ContentTypeId": "redacted",
"ForumReplyId": 9999,
"ForumThreadId": 9999,
"ForumId": 9999
}
}]
}
Sample payload data
{
"events": [
{
"TypeId": "407ad3bc-8269-493e-ac56-9127656527df",
"DateOccurred": "2015-12-04T16:31:55.5383926Z",
"EventData": {
"ActorUserId": 2100,
"ContentId": "4c792b81-6f09-4a45-be8c-476198ba47be"
}
},
{
"TypeId": "3b75c5b9-4705-4a97-93f5-a4941dc69bc9",
"DateOccurred": "2015-12-04T16:48:03.7343926Z",
"EventData": {
"ActorUserId": 2100,
"ContentId": "4c792b81-6f09-4a45-be8c-476198ba47be"
}
}
]
}
I do not know how to determine why the Azure Function is not triggered by the webhook. The software's API documentation does not seem to provide a way to look at the JSON being sent over the webhook, although in my inexperience I may be wrong.
Is there a mechanism within Azure, or Postman, or another tool that lets me see what JSON is being sent over the webhook? Or perhaps is there another approach to determining the cause of the issue?
Thank you for any help.
This is how I got the JSON file from Azure alerts.
Install Ruby on the server
Install Sinatra with following command gem install sinatra
Create file webhook.rb and paste code bellow
require 'sinatra'
set :port, 80
set :bind, '0.0.0.0'
post '/event' do
status 204 #successful request with no body content
request.body.rewind
request_payload = JSON.parse(request.body.read)
#append the payload to a file
File.open("events.txt", "a") do |f|
f.puts(request_payload)
end
end
Run the web service with command ruby webhook.rb
JSON fill be written to file events.txt

Google Apps Script UrlFetchApp isn't encoding a JSON array correctly

I've looked everywhere and can't find this issue. I've come over from PeopleSoft to .NET and have only recently began learning JavaScript and I'm attempting to use Google Apps Script to send email notification messages to Slack.
It appears to me that GAS's UrlFetchApp isn't handling an array correctly. Below I didn't include all the Slack API options for clarity. Here how I constructed the payload, where 'attachments' contains the array in question:
var payload =
{
// ...
"username": "Test webhook Bot",
"attachments": [
{
"pretext": "pre-hello1",
"text": "text-world1"
},
{
"pretext": "pre-hello2",
"text": "text-world2"
}
]
// ...
};
var options =
{
"method" : "post",
"payload" : payload,
"contentType":"application/json"
};
var response = UrlFetchApp.fetch(requestURL, options);
When testing I found that the post was occuring but Slack was ignoring the attachments portion of the message. I used the following to examine the outgoing POST:
var response = UrlFetchApp.getRequest(requestURL, options);
And what I found looking at the execution transcript I find that the JSON array in my payload isn't being encoded the way I expected. Before execution, I clearly see the properly formatted array.
[16-01-26 07:26:39:050 MST] UrlFetchApp.getRequest([https://slack.com/api/chat.postMessage?, {method=post, payload={attachments=[{pretext=pre-hello1, text=text-world1}, {pretext=pre-hello2, text=text-world2}], username=Test webhook Bot}, contentType=application/json}]) [0 seconds]
But what is actually sent, in place of the attachments array is: %5BLjava.lang.Object;#37f01fb3
[16-01-26 07:26:39:051 MST] Logger.log([Test:https://slack.com/api/chat.postMessage?attachments=%5BLjava.lang.Object;#37f01fb3&username=Test+webhook+Bot, []]) [0 seconds]
I tried searching this out as much as I could before asking for help, but I'm not sure if I'm either loss. Does anyone know where I may look to find out what I'm missing? Thanks.
To the extent that this information is helpful almost 4 years out, I've been running into the same problem and here's the solution I came up with:
- I will be including all relevant information encoded in the URL JSON structure
- The "options" portion of the UrlFetchApp is then just specifying the method and contentType
An example would look like this:
var url = "https://slack.com/api/chat.postMessage?token=the-token-here&channel=channel_id_here&text=hello%20world";
var options = {
"method": "post",
"contentType": "application/json",
};
return UrlFetchApp.fetch(url,options);
}
I also got some more helpful information at this Stack Overflow thread.
I think this is the Slack API documentation that helps explain the constraints:
JSON-encoded bodies
For these write methods, you may alternatively send your HTTP POST
data as Content-type: application/json.
There are some ground rules:
You must explicitly set the Content-type HTTP header to
application/json. We won't interpret your POST body as such without
it. You must transmit your token as a bearer token in the
Authorization HTTP header. You cannot send your token as part of the
query string or as an attribute in your posted JSON. Do not mix
arguments between query string, URL-encoded POST body, and JSON
attributes. Choose one approach per request. Providing an explicitly
null value for an attribute will result in whichever default behavior
is assigned to it.
Based on a comment I received from a Google Drive Help Forum discussion , I wanted to pass on more information on what I found regarding the use of JSON.stringify() in creating my Slack request. I modified my options JSON
var options = {
'method': 'post',
'payload': JSON.stringify(payload)
};
Google then interprets the 'attachments' array correctly when constructing the request and I no longer see the java.lang.Object error.
Additional lessons learned: prior to using JSON.stringify() Slack would let me post using my personal developer token as part of the payload. Once I began using JSON.stringify() Slack would not accept my personal token nor could I pass a channel parameter. This resulted in me creating a Slack Incoming Webhook direct to the channel I wanted. I haven't tracked down why that would be the case. It may be in Slack's documentation somewhere, I just haven't had time to look yet.

Bad Request error while using google drive api to copy file into a folder

I am trying to use the google drive api to copy a file into a folder
As the documentation says i am generating a POST request to https://www.googleapis.com/drive/v2/files/{fileId}/copy?access_token={MY_ACCESS_TOKEN}
i am using python to generate the request and in order to specify the target folder i am setting the request body to -
{
"parents":
[
{
"id":"{parent_id}"
}
]
}
so the final code is like-
url = https://www.googleapis.com/drive/v2/files/Ansjd021-23123414kjn2k3jn2/copy?access_token=Ya.asdsakjn2312k3n21kj3n-12312j3knb123l
body = {
"parents":
[
{
"id":"ZXC12312323123-Blahasd12323X"
}
]
}
request2 = urllib2.Request(url, urllib.urlencode(body))
request2_open = urllib2.urlopen(request2)
response = request2_open.read()
request2_open.close()
print response
The problem being that I am getting a Http Error : 404 Bad Request
I cant seem to figure out the problem with this. I am doing the same thing using the google playground and its running there.
I did this using https://developers.google.com/drive/v2/reference/files/copy#try-it and got ...
POST https://www.googleapis.com/drive/v2/files/1234/copy?key={YOUR_API_KEY}
Content-Type: application/json
Authorization: Bearer ya29.AHES6ZSZB-t4b4HsR5
X-JavaScript-User-Agent: Google APIs Explorer
{
"parents": [
{
"id": "1234"
}
]
}
This looks pretty much the same as your sample, except the authtoken is in an http header rather than the URL. Also, what happens if you don't urlencode the body? Is there a longer error message in the response body?