Working on API gateway and cors
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@ -62,4 +62,5 @@ typings/
|
||||
/package-lock.json
|
||||
/nbproject/private/
|
||||
.vscode
|
||||
.serverless
|
||||
.serverless
|
||||
.cache
|
@ -9,7 +9,7 @@
|
||||
"start:dev": "cross-env NODE_ENV=development \"serverless offline --port 3001\"",
|
||||
"start": "npm run start:prod",
|
||||
"watch": "npm run start:dev",
|
||||
"deploy": "echo \"Building private\"",
|
||||
"deploy": "serverless deploy",
|
||||
"test": "yarn jest"
|
||||
},
|
||||
"repository": {
|
||||
@ -34,7 +34,7 @@
|
||||
"serverless-plugin-include-dependencies": "^3.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^24.0.18",
|
||||
"@types/jest": "^25.1.1",
|
||||
"@types/node": "^12.7.1",
|
||||
"@types/nodemailer": "^6.2.1",
|
||||
"cross-env": "^5.2.0",
|
||||
|
@ -26,13 +26,19 @@ provider:
|
||||
|
||||
functions:
|
||||
ping:
|
||||
handler: dist/index.ping
|
||||
handler: dist/functions/ping/ping.ping
|
||||
events:
|
||||
- http: ANY ping
|
||||
- http:
|
||||
method: GET
|
||||
path: ping
|
||||
cors: true
|
||||
sendMail:
|
||||
handler: dist/functions/mail/send.sendMail
|
||||
events:
|
||||
- http: ANY mail/send
|
||||
- http:
|
||||
method: POST
|
||||
path: mail/send
|
||||
cors: true
|
||||
|
||||
plugins:
|
||||
- serverless-plugin-include-dependencies
|
||||
|
@ -10,16 +10,13 @@ export interface sendMailParams {
|
||||
}
|
||||
|
||||
export const sendMail = withHandler<sendMailParams>(async (e,c) => {
|
||||
//Required
|
||||
if(!e || !e.body) return { statusCode: 400, body: 'Missing Contact Details' };
|
||||
if(!e.body) return { statusCode: 400, body: 'Missing Contact Details' };
|
||||
|
||||
let { name, email, message } = e.body;
|
||||
|
||||
if(!name) return { statusCode: 400, body: 'Missing Contact Name' };
|
||||
if(!email) return { statusCode: 400, body: 'Missing Contact Email' };
|
||||
if(!message) return { statusCode: 400, body: 'Missing Contact Message' };
|
||||
|
||||
|
||||
//Validate
|
||||
if(name.length > 128 || !name.replace(/\s/g, '').length) return { statusCode: 400, body: 'Invalid Name' };
|
||||
if(!validate(email)) return { statusCode: 400, body: 'Invalid Email' };
|
||||
@ -55,5 +52,5 @@ export const sendMail = withHandler<sendMailParams>(async (e,c) => {
|
||||
<span>Time: ${new Date().toLocaleString()}
|
||||
`
|
||||
});
|
||||
return { statusCode: 200, body: true }
|
||||
return { statusCode: 200, body: x && x.accepted && x.accepted.length }
|
||||
});
|
@ -2,6 +2,7 @@ import { ping } from './../ping';
|
||||
|
||||
describe('ping', () => {
|
||||
it('shold return a hello world and a 200 code', async () => {
|
||||
await expect(ping()).resolves.toStrictEqual({ statusCode: 200, body: 'Thank funk!' });
|
||||
await expect(ping()).resolves.toHaveProperty('body', 'Thank funk!');
|
||||
await expect(ping()).resolves.toHaveProperty('statusCode', 200);
|
||||
})
|
||||
})
|
@ -1,4 +1,4 @@
|
||||
import { withHandler, APICallable } from './../handler';
|
||||
import { withHandler, APICallable, DEFAULT_HEADERS } from './../handler';
|
||||
|
||||
describe('withHandler', () => {
|
||||
it('should wrap an async function into a serverless callbackable function', () => {
|
||||
@ -28,7 +28,7 @@ describe('withHandler', () => {
|
||||
await new Promise(resolve => setImmediate(resolve));
|
||||
|
||||
expect(fn).toHaveBeenCalledWith(null, { body: '"Hello World"', statusCode: 200,
|
||||
headers: { 'Content-Type': 'application/json'}
|
||||
headers: DEFAULT_HEADERS
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1,3 +1,9 @@
|
||||
export const DEFAULT_HEADERS = {
|
||||
'Content-Type': 'application/json',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Credentials': true
|
||||
}
|
||||
|
||||
export type APIResponse = {
|
||||
statusCode?:number;
|
||||
body:any;
|
||||
@ -28,42 +34,36 @@ export interface APIEvent<T=any> {
|
||||
|
||||
export const withHandler = <T=any>(callable:APICallable<T>) => {
|
||||
return (event?:APIEvent<T>, context?, callback?) => {
|
||||
if(event && event.headers && event.headers['Content-Type']) {
|
||||
let contentType = event.headers['Content-Type'];
|
||||
if(contentType.indexOf('application/json') !== -1) {
|
||||
try {
|
||||
let body:T = JSON.parse(event.body as any);
|
||||
event.body = body;
|
||||
} catch(e) {
|
||||
callback(null, {
|
||||
statusCode: 400,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify('Invalid body')
|
||||
})
|
||||
}
|
||||
}
|
||||
try {
|
||||
if(!event) throw new Error();
|
||||
if(event.body) event.body = JSON.parse(event.body as any) as T;
|
||||
} catch(e) {
|
||||
console.error(e);
|
||||
callback(null, {
|
||||
statusCode: 400, headers: DEFAULT_HEADERS,
|
||||
body: JSON.stringify('Invalid body')
|
||||
});
|
||||
}
|
||||
|
||||
return callable(event, context).then(d => {
|
||||
if(callback) {
|
||||
let contentType = (d.headers ? d.headers['Content-Type']:null) ||'application/json';
|
||||
let json = contentType == 'application/json';
|
||||
if(!callback) return d;
|
||||
let contentType = (d.headers?d.headers['Content-Type']:null) ||'application/json';
|
||||
let json = contentType.includes('application/json');
|
||||
|
||||
callback(null, {
|
||||
...d,
|
||||
body: json ? JSON.stringify(d.body) : d.body,
|
||||
statusCode: d.statusCode || 200,
|
||||
headers: {
|
||||
...(d.headers||{}),
|
||||
"Content-Type": contentType
|
||||
}
|
||||
});
|
||||
}
|
||||
callback(null, {
|
||||
...d,
|
||||
body: json ? JSON.stringify(d.body) : d.body,
|
||||
statusCode: d.statusCode || 200,
|
||||
headers: {
|
||||
...DEFAULT_HEADERS,
|
||||
...(d.headers||{})
|
||||
}
|
||||
});
|
||||
|
||||
return d;
|
||||
}).catch(ex => {
|
||||
if(callback) {
|
||||
callback(null, { statusCode: 500, body: null, });
|
||||
callback(null, { statusCode: 500, body: null, headers: DEFAULT_HEADERS });
|
||||
}
|
||||
throw ex;
|
||||
})
|
||||
|
@ -7,7 +7,7 @@
|
||||
"develop": "gatsby develop",
|
||||
"start": "npm run develop",
|
||||
"serve": "gatsby serve",
|
||||
"deploy": "echo \"Building public\"",
|
||||
"deploy": "serverless client deploy",
|
||||
"clean": "gatsby clean"
|
||||
},
|
||||
"repository": {
|
||||
@ -27,6 +27,7 @@
|
||||
},
|
||||
"homepage": "https://domsplace.com",
|
||||
"dependencies": {
|
||||
"axios": "^0.19.2",
|
||||
"babel-plugin-styled-components": "^1.10.7",
|
||||
"gatsby": "^2.18.12",
|
||||
"gatsby-image": "^2.2.39",
|
||||
@ -47,11 +48,14 @@
|
||||
"yup": "^0.28.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"serverless": "^1.63.0",
|
||||
"serverless-finch": "^2.5.2",
|
||||
"serverless-plugin-include-dependencies": "^4.0.1",
|
||||
"@types/node": "^13.5.0",
|
||||
"@types/react": "^16.9.19",
|
||||
"@types/react-dom": "^16.9.5",
|
||||
"@types/styled-components": "^4.4.2",
|
||||
"@types/react-helmet": "^5.0.15",
|
||||
"@types/styled-components": "^4.4.2",
|
||||
"@types/yup": "^0.26.29"
|
||||
},
|
||||
"browserslist": [
|
||||
|
@ -3,6 +3,13 @@ service: domsplace
|
||||
|
||||
frameworkVersion: ">=1.26.0"
|
||||
|
||||
provider:
|
||||
name: aws
|
||||
runtime: nodejs10.x
|
||||
stage: ${opt:stage, "test"}
|
||||
region: ap-southeast-2
|
||||
memorySize: 512
|
||||
|
||||
package:
|
||||
excludeDevDependencies: false
|
||||
individually: true
|
||||
@ -16,6 +23,6 @@ plugins:
|
||||
custom:
|
||||
client:
|
||||
bucketName: domsplace-${self:provider.stage}-${self:provider.region}-public
|
||||
distributionFolder: frontned/public/
|
||||
distributionFolder: public/
|
||||
indexDocument: index.html
|
||||
errorDocument: index.html
|
5
src/public/src/api/Client.tsx
Normal file
5
src/public/src/api/Client.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
import axios from 'axios';
|
||||
|
||||
export const Client = axios.create({
|
||||
baseURL: 'https://api.domsplace.com/v1/'
|
||||
});
|
@ -1,12 +1,8 @@
|
||||
export const sendMail = (name:string, email:string, message:string) => {
|
||||
return fetch('https://api.domsplace.com/v1/mail/send', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
name, email, message
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
}
|
||||
}).then(d => d.json());
|
||||
}
|
||||
import { Client } from "./Client";
|
||||
|
||||
export const sendMail = (name:string, email:string, message:string) => Client.post('mail/send', {
|
||||
name, email, message
|
||||
});
|
||||
|
||||
///@ts-ginore
|
||||
(globalThis as any)['sendMail' as any] = sendMail as any;
|
Reference in New Issue
Block a user