Skip to content

Commit

Permalink
Get notified (#19)
Browse files Browse the repository at this point in the history
# Description

Adds a get notified tag and form and privacy policy

- Closes #18 


## Type of change

Please delete options that are not relevant.

- [x] Content Change (Required approval in Slack: `#frequency-xyz` and
remember that changes along the way trigger
      re-approval.)
  - [x] Approved HE (Required for technical wording)
  - [x] Approved CM
- [x] New Feature

# How to Test?

Please describe how to test that you ran to verify your changes. Provide
instructions so we can reproduce. Please also
list any relevant details for your test configuration

1. Pull and run locally
2. See that the get notified button on the right doesn't cover important
text
3. Click the button and see that it loads the form
4. Form errors
5. Thank you after submitting the form

# Checklist:

- [x] I have performed a self-review of my code
- [ ] I have commented my code & PR, particularly in hard-to-understand
areas
- [x] I have checked at all the breakpoints to make sure it works on all
screen sizes
  • Loading branch information
wilwade authored Sep 16, 2024
1 parent eeb64b4 commit b0b7394
Show file tree
Hide file tree
Showing 27 changed files with 1,050 additions and 63 deletions.
82 changes: 82 additions & 0 deletions cors-proxy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Serverless CORS Proxy

This is a simple serverless CORS proxy that supports `POST` requests.

This is used by the contact form.

## Features

- Supports `POST` requests to a single `PROXY_TARGET_URL`
- Adds CORS headers for cross-origin requests

## Serverless.yaml

See [./serverless.yaml] to use [serverless.com config](https://www.serverless.com/)

## Environment Variables

These are the environment variables used by the handler.

- `PROXY_TARGET_URL`: Where the proxy will redirect the requests to
- `PROXY_ALLOWED_ORIGIN`: (Default `'*'`) The `Access-Control-Allow-Origin` string for the local server.

## Setup

### 1. Running Locally

To run the CORS proxy locally:

1. Run the proxy locally:

```bash
PROXY_TARGET_URL="https://example.com/submit-form" npm run start
```

- Replace `https://example.com/submit-form` with the target URL.

2. Use the following `curl` example to test a `POST` request from your terminal:

```bash
curl -X POST "http://localhost:3000/" \
-d "param1=value1&param2=value2"
```

- Replace `param1=value1&param2=value2` with your actual form data.

### 2. Using with an HTML Form and JavaScript Fetch

You can use this proxy to submit a form using JavaScript `fetch`. Here’s an example:

#### HTML Form:

```html
<form id="exampleForm">
<input type="text" name="param1" value="value1" />
<input type="text" name="param2" value="value2" />
<button type="submit">Submit</button>
</form>

<script>
document.getElementById('exampleForm').addEventListener('submit', async (e) => {
e.preventDefault(); // Prevent the default form submission
const formData = new FormData(e.target);
const params = new URLSearchParams(formData).toString();
try {
const response = await fetch('https://localhost:3000', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: params,
});
const result = await response.json();
console.log(result); // Handle the response
} catch (error) {
console.error('Error:', error);
}
});
</script>
```
49 changes: 49 additions & 0 deletions cors-proxy/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import https from 'node:https';
import process from 'node:process';

export const handler = async (event) => {
const targetUrl = process.env.PROXY_TARGET_URL;

const postData = event.body;

const options = {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
};

return new Promise((resolve, _reject) => {
const req = https.request(targetUrl, options, (response) => {
let data = '';

// Collect response data
response.on('data', (chunk) => (data += chunk));

// When the request is complete
response.on('end', () => {
resolve({
statusCode: 200,
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
status: response.statusCode,
headers: response.headers,
body: data,
}),
});
});
});

req.on('error', (error) => {
resolve({
statusCode: 500,
body: JSON.stringify({ message: 'Error in request', error: error.message }),
});
});

req.write(postData);
req.end();
});
};
11 changes: 11 additions & 0 deletions cors-proxy/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "cors-proxy",
"type": "module",
"version": "1.0.0",
"description": "A simple CORS proxy for serverless environments.",
"main": "index.mjs",
"scripts": {
"start": "node server.mjs"
},
"dependencies": {}
}
67 changes: 67 additions & 0 deletions cors-proxy/server.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import http from 'http';
import { handler } from './index.mjs';
import url from 'url';
import process from 'node:process';

const allowedOrigin = process.env.PROXY_ALLOWED_ORIGIN || '*';

// Function to parse the HTTP request body
const getRequestBody = (req) => {
return new Promise((resolve, reject) => {
let body = '';
req.on('data', (chunk) => {
body += chunk.toString();
});
req.on('end', () => {
resolve(body);
});
req.on('error', (err) => {
reject(err);
});
});
};

// Start the HTTP server
const server = http.createServer(async (req, res) => {
// Set CORS headers
res.setHeader('Access-Control-Allow-Origin', allowedOrigin);
res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');

// Handle OPTIONS request for CORS preflight
if (req.method === 'OPTIONS') {
res.writeHead(200);
res.end();
return;
}

if (req.method === 'POST') {
const parsedUrl = url.parse(req.url, true);
const body = await getRequestBody(req);

// Convert HTTP request into a Lambda event format
const lambdaEvent = {
httpMethod: req.method,
queryStringParameters: parsedUrl.query,
body: body,
};

// Call the handler (same code used in AWS Lambda)
const lambdaResponse = await handler(lambdaEvent);

// Send response
res.writeHead(lambdaResponse.statusCode, {
...lambdaResponse.headers,
'Access-Control-Allow-Origin': '*', // Make sure to include CORS in response too
});
res.end(lambdaResponse.body);
} else {
res.statusCode = 405;
res.end('Only POST requests are supported');
}
});

// Start server on port 3000
server.listen(3000, () => {
console.log('Local server running on http://localhost:3000');
});
18 changes: 18 additions & 0 deletions cors-proxy/serverless.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
service: xyz-form-cors-proxy

frameworkVersion: '4'

provider:
name: aws
runtime: nodejs20.x

functions:
hello:
handler: handler.handler
events:
- http:
method: post
cors:
origin: 'https://*.frequency.xyz'
headers:
- Content-Type
6 changes: 3 additions & 3 deletions src/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<link rel="icon" href="%sveltekit.assets%/favicon.svg" type="image/svg+xml" />
<link rel="apple-touch-icon" href="%sveltekit.assets%/apple-touch-icon.png" />
<link rel="manifest" href="%sveltekit.assets%/manifest.webmanifest" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />

<meta property="og:title" content="Frequency" />
<meta property="og:url" content="" />
Expand All @@ -35,8 +35,8 @@
%sveltekit.head%

<!-- Klaro - make sure the config gets loaded before Klaro -->
<script defer type="text/javascript" src="klaro-config.js"></script>
<script defer type="text/javascript" src="klaro.js"></script>
<script defer type="text/javascript" src="/klaro-config.js"></script>
<script defer type="text/javascript" src="/klaro.js"></script>
<!-- Matomo -->
<script>
var _paq = (window._paq = window._paq || []);
Expand Down
2 changes: 2 additions & 0 deletions src/components/Footer.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<footer class="freq-container flex h-[50px] items-center justify-end gap-3 text-xs font-semibold">
<div>© {new Date().getFullYear()} Frequency Network Foundation</div>
<span class="h-4 w-[2px] bg-black" />
<a href="/privacy">Privacy Policy</a>
<span class="h-4 w-[2px] bg-black" />
<div class="whitespace-nowrap">All Rights Reserved</div>
</footer>
Loading

0 comments on commit b0b7394

Please sign in to comment.