Created
July 2, 2022 02:38
-
-
Save Fredkiss3/c3d9ae31aab6e2fe5c264ad3dd7d1cbe to your computer and use it in GitHub Desktop.
Script for cloudfare worker to post to a notion database
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const corsHeaders = { | |
'Access-Control-Allow-Origin': '*', | |
'Access-Control-Allow-Methods': 'GET,HEAD,POST,OPTIONS', | |
'Access-Control-Allow-Credentials': true, | |
}; | |
const ALLOWED_HOSTS = [ | |
// Put your allowed cors hosts here | |
// By default localhost is allowed | |
// Your fetch should have a `mode: cors` enabled for it to work | |
]; | |
addEventListener('fetch', (event) => { | |
const request = event.request; | |
const url = new URL(request.url); | |
if (request.method === 'OPTIONS') { | |
// Handle CORS preflight requests | |
event.respondWith(handleOptions(request)); | |
} else { | |
event.respondWith(handleRequest(event.request)); | |
} | |
}); | |
/** | |
* This function is used to handle CORS requests | |
* @param request | |
* @returns | |
*/ | |
function handleOptions(request) { | |
// Make sure the necessary headers are present | |
// for this to be a valid pre-flight request | |
let headers = request.headers; | |
if ( | |
headers.get('Origin') !== null && | |
headers.get('Access-Control-Request-Method') !== null && | |
headers.get('Access-Control-Request-Headers') !== null | |
) { | |
// Handle CORS pre-flight request. | |
// If you want to check or reject the requested method + headers | |
// you can do that here. | |
let respHeaders = { | |
...corsHeaders, | |
// Allow all future content Request headers to go back to browser | |
// such as Authorization (Bearer) or X-Client-Name-Version | |
Allow: 'POST, OPTIONS', | |
'Access-Control-Allow-Origin': | |
ALLOWED_HOSTS.includes(headers.get('Origin')) || | |
headers.get('Origin').startsWith(`http://localhost`) | |
? headers.get('Origin') | |
: null, | |
'Access-Control-Allow-Headers': request.headers.get( | |
'Access-Control-Request-Headers' | |
), | |
}; | |
return new Response(null, { | |
headers: respHeaders, | |
}); | |
} else { | |
// Handle standard OPTIONS request. | |
// If you want to allow other HTTP Methods, you can do that here. | |
return new Response(null, { | |
headers: { | |
Allow: 'POST, OPTIONS', | |
}, | |
}); | |
} | |
} | |
/** | |
* Worker Code for posting to Notion | |
* @param request Request | |
* @returns Response | |
*/ | |
async function handleRequest(request) { | |
const { headers } = request; | |
const contentType = headers.get('content-type') || ''; | |
// Secret Token to not allow anyone to call this api | |
const token = headers.get('Token') || ''; | |
let status = 200; | |
let error = null; | |
// Accept only JSON post requests | |
if ( | |
request.method === 'POST' && | |
contentType.includes('application/json') && | |
token.length > 0 && | |
token === SECRET_TOKEN | |
) { | |
try { | |
const { email, contact, name } = await request.json(); | |
// formBody should have name and contact filled | |
await fetch(`https://api.notion.com/v1/pages`, { | |
method: 'POST', | |
body: JSON.stringify({ | |
parent: { | |
type: 'database_id', | |
database_id: NOTION_DATABASE_ID, | |
}, | |
// Refer to notion documentation => https://developers.notion.com/reference/property-value-object | |
// and adapt to your needs | |
// For this case the database is structured like this : | |
// - name : string (and used as the title) | |
// - contact : phone number | |
// - email : email | |
properties: { | |
contact: { | |
type: 'phone_number', | |
phone_number: contact, | |
}, | |
email: email | |
? { | |
type: 'email', | |
email: email, | |
} | |
: undefined, | |
name: { | |
id: 'title', | |
type: 'title', | |
title: [ | |
{ | |
type: 'text', | |
text: { content: name }, | |
}, | |
], | |
}, | |
}, | |
}), | |
headers: { | |
'Notion-Version': '2022-02-22', | |
'Content-Type': 'application/json', | |
Accept: 'application/json', | |
Authorization: `Bearer ${NOTION_KEY}`, | |
}, | |
}); | |
} catch (e) { | |
error = `Your form has not been filled correctly.`; | |
status = 400; | |
} | |
} else if (request.method !== 'POST') { | |
error = 'Only POST method is allowed'; | |
status = 405; | |
} else if (token.length === 0 || token !== SECRET_TOKEN) { | |
error = 'Unauthorized'; | |
status = 401; | |
} else if (!contentType.includes('application/json')) { | |
error = `Expected content-type of JSON, given ${contentType}`; | |
status = 415; | |
} | |
return new Response( | |
JSON.stringify({ | |
error, | |
}), | |
{ | |
headers: { | |
'Content-Type': 'application/json', | |
'Access-Control-Allow-Origin': | |
ALLOWED_HOSTS.includes(headers.get('Origin')) || // allowed hosts | |
headers.get('Origin').startsWith(`http://localhost`) // localhost | |
? headers.get('Origin') | |
: null, | |
}, | |
status, | |
} | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
MAGNIFIQUE