|
const WEBHOOK_HOST = "<replace with your host>"; |
|
const WEBHOOK_PATH = "<replace with your path>"; |
|
|
|
function signAndSend(body) { |
|
const signingKey = "-----BEGIN PRIVATE KEY-----\nREPLACE WITH YOUR PKCS8 ENCODED PRIVATE RSA KEY \n-----END PRIVATE KEY-----" |
|
|
|
// Serialize payload request |
|
const payload = JSON.stringify(body) |
|
|
|
// Pack signature parameters |
|
const now = Math.floor((new Date).getTime() / 1000); |
|
const nonce = Utilities.getUuid(); |
|
const sigParams = '("@method" "@authority" "@path" "content-type" "content-digest" "content-length");created=' + now + ';keyid="<replace with your expected subject>";nonce="' + nonce + '"' |
|
|
|
// Compute content digest |
|
const contentDigest = 'sha-512=:' + Utilities.base64Encode(Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_512, payload)) + ':'; |
|
|
|
// Prepare protected content to sign |
|
var protected = '"@method": POST' + "\n"; |
|
protected += '"@authority": ' + WEBHOOK_HOST + "\n"; |
|
protected += '"@path": ' + WEBHOOK_PATH + "\n"; |
|
protected += '"content-type": application/json' + "\n"; |
|
protected += '"content-digest": ' + contentDigest + "\n"; |
|
protected += '"content-length": ' + payload.length + "\n"; |
|
protected += '"@signature-params": ' + sigParams; |
|
|
|
// Sign the protected content |
|
const signatureBytes = Utilities.computeRsaSignature(Utilities.RsaAlgorithm.RSA_SHA_256, protected, signingKey); |
|
const signature = Utilities.base64Encode(signatureBytes); |
|
|
|
const options = { |
|
"method": "post", |
|
"headers": { |
|
"Content-Type": "application/json", |
|
"Content-Digest": contentDigest, |
|
"Signature-Input": "sig=" + sigParams, |
|
"Signature": "sig=:" + signature + ":", |
|
}, |
|
"payload": payload, |
|
"muteHttpExceptions": true, |
|
} |
|
const response = UrlFetchApp.fetch("https://"+WEBHOOK_HOST+WEBHOOK_PATH, options); |
|
Logger.log(response); |
|
} |
|
|
|
function debugPost() { |
|
signAndSend({"test": true}) |
|
} |
|
|
|
function doPost(e) { |
|
// http://googleappsdeveloper.blogspot.co.uk/2011/10/concurrency-and-google-apps-script.html |
|
var lock = LockService.getPublicLock(); |
|
lock.waitLock(10000); // wait 10 seconds before conceding defeat. |
|
|
|
try { |
|
// Retrieve last submission |
|
const form = FormApp.getActiveForm(); |
|
const allResponses = form.getResponses(); |
|
const latestResponse = allResponses[allResponses.length - 1]; |
|
const response = latestResponse.getItemResponses(); |
|
|
|
// Prepare payload |
|
var items = []; |
|
for (var i = 0; i < response.length; i++) { |
|
const question = response[i].getItem().getTitle(); |
|
const answer = response[i].getResponse(); |
|
items.push({"question":question, "answer": answer}); |
|
} |
|
|
|
// Send to webhook endpoint |
|
signAndSend({ |
|
"@timestamp": latestResponse.getTimestamp(), |
|
"@id": e.response.getId(), |
|
"@type": "form_posted", |
|
"email": latestResponse.getRespondentEmail(), |
|
"responses": items, |
|
}); |
|
} catch (err) { |
|
Logger.log(err); |
|
} finally { //release lock |
|
lock.releaseLock(); |
|
} |
|
} |