Complete swap from express and aws to express and heroku due to the much smaller learning curve needed for a herkou build
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
#ignore all env files
|
||||||
|
*.env
|
||||||
|
node_modules
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
const Msg = require('../models/msg'); //import msg model
|
||||||
|
|
||||||
|
|
||||||
|
//GET all messages
|
||||||
|
const getAllMsg = (req, res) => {
|
||||||
|
Msg.find({}, (err, data)=>{
|
||||||
|
if (err){
|
||||||
|
return res.json({Error: err});
|
||||||
|
}
|
||||||
|
return res.json(data);
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
//POST message
|
||||||
|
const newMsg = (req, res) => {
|
||||||
|
//check if the id already exists in db
|
||||||
|
Msg.findOne({ id: req.body.id }, (err, data) => {
|
||||||
|
|
||||||
|
//if tea not in db, add it
|
||||||
|
if (!data) {
|
||||||
|
//create a new tea object using the Msg model and req.body
|
||||||
|
const newMsg = new Msg({
|
||||||
|
id:req.body.id,
|
||||||
|
message: req.body.message,
|
||||||
|
time: Date.now(),
|
||||||
|
})
|
||||||
|
|
||||||
|
// save this object to database
|
||||||
|
newMsg.save((err, data)=>{
|
||||||
|
if(err) return res.json({Error: err});
|
||||||
|
return res.json(data);
|
||||||
|
})
|
||||||
|
//if there's an error or the msg is in db, return an error message
|
||||||
|
}else{
|
||||||
|
if(err) return res.json(`Something went wrong, please try again. ${err}`);
|
||||||
|
return res.json({message:"Msg already exists"});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
//DELETE all messages
|
||||||
|
const deleteAllMsg = (req, res) => {
|
||||||
|
Msg.deleteMany({}, err => {
|
||||||
|
if(err) {
|
||||||
|
return res.json({message: "Deletion of all messages failed"});
|
||||||
|
}
|
||||||
|
return res.json({message: "Deletion of all messages successful"});
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
//GET message based on id
|
||||||
|
const getOneMsg = (req, res) => {
|
||||||
|
let id = req.params.id; //get the msg id
|
||||||
|
|
||||||
|
//find the specific msg with that id
|
||||||
|
Msg.findOne({id:id}, (err, data) => {
|
||||||
|
if(err || !data) {
|
||||||
|
return res.json({message: "Message doesn't exist."});
|
||||||
|
}
|
||||||
|
else return res.json(data); //return the msg object if found
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
//DELETE message based on id
|
||||||
|
const deleteOneMsg = (req, res) => {
|
||||||
|
let id = req.params.id; // get the id of msg to delete
|
||||||
|
|
||||||
|
Msg.deleteOne({id:id}, (err, data) => {
|
||||||
|
//if there's nothing to delete return a message
|
||||||
|
if( data.deletedCount == 0) return res.json({message: "Message doesn't exist."});
|
||||||
|
//else if there's an error, return the err message
|
||||||
|
else if (err) return res.json(`Something went wrong, please try again. ${err}`);
|
||||||
|
//else, return the success message
|
||||||
|
else return res.json({message: "Message deleted."});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
//export controller functions
|
||||||
|
module.exports = {
|
||||||
|
getAllMsg,
|
||||||
|
newMsg,
|
||||||
|
deleteAllMsg,
|
||||||
|
getOneMsg,
|
||||||
|
deleteOneMsg
|
||||||
|
};
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<h1>Welcome to RESTapi Demo</h1>
|
||||||
|
<p>Enjoy sending messages around</p>
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
var AWS = require('aws-sdk');
|
|
||||||
|
|
||||||
// Get "Hello" Dynamo table name. Replace DEFAULT_VALUE
|
|
||||||
// with the actual table name from your stack.
|
|
||||||
const helloDBArn = process.env['HELLO_DB'] || 'DEFAULT_VALUE'; //'Mark-HelloTable-1234567';
|
|
||||||
const helloDBArnArr = helloDBArn.split('/');
|
|
||||||
const helloTableName = helloDBArnArr[helloDBArnArr.length - 1];
|
|
||||||
|
|
||||||
// handleHttpRequest is the entry point for Lambda requests
|
|
||||||
exports.handleHttpRequest = function(request, context, done) {
|
|
||||||
try {
|
|
||||||
const userId = request.pathParameters.userId;
|
|
||||||
let response = {
|
|
||||||
headers: {},
|
|
||||||
body: '',
|
|
||||||
statusCode: 200
|
|
||||||
};
|
|
||||||
|
|
||||||
switch (request.httpMethod) {
|
|
||||||
case 'GET': {
|
|
||||||
console.log('GET');
|
|
||||||
let dynamo = new AWS.DynamoDB();
|
|
||||||
var params = {
|
|
||||||
TableName: helloTableName,
|
|
||||||
Key: { 'user_id' : { S: userId } },
|
|
||||||
ProjectionExpression: 'email'
|
|
||||||
};
|
|
||||||
// Call DynamoDB to read the item from the table
|
|
||||||
dynamo.getItem(params, function(err, data) {
|
|
||||||
if (err) {
|
|
||||||
console.log("Error", err);
|
|
||||||
throw `Dynamo Get Error (${err})`
|
|
||||||
} else if (data.Item) {
|
|
||||||
console.log("Success", data.Item.email);
|
|
||||||
response.body = JSON.stringify({ "email": data.Item.email.S });
|
|
||||||
done(null, response);
|
|
||||||
} else {
|
|
||||||
console.log("Not found id=", userId);
|
|
||||||
response.body = "Not found"
|
|
||||||
response.statusCode = 404
|
|
||||||
done(null, response);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'POST': {
|
|
||||||
console.log('POST');
|
|
||||||
let bodyJSON = JSON.parse(request.body || '{}');
|
|
||||||
let dynamo = new AWS.DynamoDB();
|
|
||||||
let params = {
|
|
||||||
TableName: helloTableName,
|
|
||||||
Item: {
|
|
||||||
'user_id': { S: userId },
|
|
||||||
'email': { S: bodyJSON['email'] }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
dynamo.putItem(params, function(error, data) {
|
|
||||||
if (error) throw `Dynamo Error (${error})`;
|
|
||||||
else done(null, response);
|
|
||||||
})
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
done(e, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
const mongoose = require("mongoose"); //import mongoose
|
||||||
|
|
||||||
|
// msg schema
|
||||||
|
const MsgSchema = new mongoose.Schema({
|
||||||
|
id: {type:Number, required:true},
|
||||||
|
message: {type:String, required:true},
|
||||||
|
time: {type:Date, required:true}
|
||||||
|
})
|
||||||
|
|
||||||
|
const Msg = mongoose.model('Msg', MsgSchema); //convert to model named Msg
|
||||||
|
module.exports = Msg; //export for controller use
|
||||||
Generated
+1769
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"name": "restapi_demo",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "REST api written with express and run with heroku",
|
||||||
|
"main": "server.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node server.js",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/gjcampbell777/RESTapi_demo.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"js",
|
||||||
|
"express",
|
||||||
|
"node",
|
||||||
|
"heroku",
|
||||||
|
"rest",
|
||||||
|
"api"
|
||||||
|
],
|
||||||
|
"author": "Gregory Campbell",
|
||||||
|
"license": "ISC",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/gjcampbell777/RESTapi_demo/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/gjcampbell777/RESTapi_demo#readme",
|
||||||
|
"dependencies": {
|
||||||
|
"compression": "^1.7.4",
|
||||||
|
"dotenv": "^10.0.0",
|
||||||
|
"express": "^4.17.1",
|
||||||
|
"helmet": "^4.6.0",
|
||||||
|
"mongoose": "^6.0.13",
|
||||||
|
"multer": "^1.4.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
const express = require('express'); //import express
|
||||||
|
const multer = require('multer');
|
||||||
|
const upload = multer();
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
const msgController = require('../controllers/msg');
|
||||||
|
|
||||||
|
router.post('/msg', upload.none(), msgController.newMsg);
|
||||||
|
|
||||||
|
router.get('/msg', msgController.getAllMsg);
|
||||||
|
router.post('/msg', msgController.newMsg);
|
||||||
|
router.delete('/msg', msgController.deleteAllMsg);
|
||||||
|
|
||||||
|
router.get('/msg/:id', msgController.getOneMsg);
|
||||||
|
//router.put('/msg/:id', msgController.updateMsg);
|
||||||
|
router.delete('/msg/:id', msgController.deleteOneMsg);
|
||||||
|
|
||||||
|
module.exports = router; //export to use in server.js
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
require('dotenv').config({ path: 'development.env' });
|
||||||
|
|
||||||
|
const express = require('express');
|
||||||
|
const routes = require('./routes/msg'); //import the routes
|
||||||
|
const mongoose = require('mongoose'); //import mongoose
|
||||||
|
const helemt = require('helmet'); //import helmet
|
||||||
|
const compression = require('compression'); //import compression
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
app.use(helmet());
|
||||||
|
app.use(compression()); //compress all routes
|
||||||
|
|
||||||
|
mongoose.connect(
|
||||||
|
process.env.MONGODB_URI,
|
||||||
|
{
|
||||||
|
server: { socketOptions: { keepAlive: 300000, connectTimeoutMS: 30000 } },
|
||||||
|
replset: { socketOptions: { keepAlive: 300000, connectTimeoutMS : 30000 } },
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
if (err) return console.log("Error: ", err);
|
||||||
|
console.log("MongoDB Connection -- Ready state is:", mongoose.connection.readyState);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
app.use(express.json()); //parses incoming requests with JSON payloads
|
||||||
|
|
||||||
|
app.use('/', routes); //to use the routes
|
||||||
|
|
||||||
|
app.route('/')
|
||||||
|
.get(function (req, res) {
|
||||||
|
res.sendFile(process.cwd() + '/index.html');
|
||||||
|
});
|
||||||
|
|
||||||
|
const listener = app.listen(process.env.PORT || 3000, () => {
|
||||||
|
console.log('App is listening on port ' + listener.address().port)
|
||||||
|
})
|
||||||
|
|
||||||
-171
@@ -1,171 +0,0 @@
|
|||||||
---
|
|
||||||
AWSTemplateFormatVersion: 2010-09-09
|
|
||||||
|
|
||||||
Description: API Gateway, Lambda, and Dynamo.
|
|
||||||
|
|
||||||
Resources:
|
|
||||||
# Policy required for all lambda function roles.
|
|
||||||
BaseLambdaExecutionPolicy:
|
|
||||||
Type: AWS::IAM::ManagedPolicy
|
|
||||||
Properties:
|
|
||||||
Description: Base permissions needed by all lambda functions.
|
|
||||||
PolicyDocument:
|
|
||||||
Version: '2012-10-17'
|
|
||||||
Statement:
|
|
||||||
- Effect: Allow
|
|
||||||
Action:
|
|
||||||
- logs:CreateLogGroup
|
|
||||||
- logs:CreateLogStream
|
|
||||||
- logs:PutLogEvents
|
|
||||||
- ec2:CreateNetworkInterface
|
|
||||||
- ec2:DescribeNetworkInterfaces
|
|
||||||
- ec2:DeleteNetworkInterface
|
|
||||||
Resource: "*"
|
|
||||||
|
|
||||||
HelloTable:
|
|
||||||
Type: AWS::DynamoDB::Table
|
|
||||||
Properties:
|
|
||||||
ProvisionedThroughput:
|
|
||||||
ReadCapacityUnits: 5
|
|
||||||
WriteCapacityUnits: 5
|
|
||||||
AttributeDefinitions:
|
|
||||||
- AttributeName: user_id
|
|
||||||
AttributeType: S
|
|
||||||
KeySchema:
|
|
||||||
- AttributeName: user_id
|
|
||||||
KeyType: HASH
|
|
||||||
|
|
||||||
# FIXME How to hook up custom domain?
|
|
||||||
MyApiGateway:
|
|
||||||
Type: AWS::ApiGateway::RestApi
|
|
||||||
Properties:
|
|
||||||
Name: !Sub "${AWS::StackName}-MyApiGateway"
|
|
||||||
Description: A description
|
|
||||||
FailOnWarnings: true
|
|
||||||
Body:
|
|
||||||
swagger: 2.0
|
|
||||||
info:
|
|
||||||
description: |
|
|
||||||
The account API.
|
|
||||||
version: 1.0
|
|
||||||
basePath: /
|
|
||||||
schemes:
|
|
||||||
- https
|
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
produces:
|
|
||||||
- application/json
|
|
||||||
paths:
|
|
||||||
/users/{userId}/hello:
|
|
||||||
get:
|
|
||||||
description: TBD
|
|
||||||
x-amazon-apigateway-integration:
|
|
||||||
uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HelloLambda.Arn}/invocations"
|
|
||||||
credentials: !GetAtt MyApiGatewayRole.Arn
|
|
||||||
passthroughBehavior: when_no_match
|
|
||||||
httpMethod: POST
|
|
||||||
type: aws_proxy
|
|
||||||
operationId: getHello
|
|
||||||
parameters:
|
|
||||||
- name: userId
|
|
||||||
in: path
|
|
||||||
description: TBD
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
format: uuid
|
|
||||||
post:
|
|
||||||
description: TBD
|
|
||||||
x-amazon-apigateway-integration:
|
|
||||||
uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HelloLambda.Arn}/invocations"
|
|
||||||
credentials: !GetAtt MyApiGatewayRole.Arn
|
|
||||||
passthroughBehavior: when_no_match
|
|
||||||
httpMethod: POST
|
|
||||||
type: aws_proxy
|
|
||||||
operationId: postHello
|
|
||||||
parameters:
|
|
||||||
- name: userId
|
|
||||||
in: path
|
|
||||||
description: TBD
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
format: uuid
|
|
||||||
- name: body
|
|
||||||
in: body
|
|
||||||
description: TBD
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
required:
|
|
||||||
- email
|
|
||||||
properties:
|
|
||||||
email:
|
|
||||||
type: string
|
|
||||||
|
|
||||||
MyApiGatewayDeployment:
|
|
||||||
Type: AWS::ApiGateway::Deployment
|
|
||||||
Properties:
|
|
||||||
RestApiId: !Ref MyApiGateway
|
|
||||||
StageName: prod
|
|
||||||
|
|
||||||
MyApiGatewayRole:
|
|
||||||
Type: AWS::IAM::Role
|
|
||||||
Properties:
|
|
||||||
AssumeRolePolicyDocument:
|
|
||||||
Version: '2012-10-17'
|
|
||||||
Statement:
|
|
||||||
- Effect: Allow
|
|
||||||
Principal:
|
|
||||||
Service: apigateway.amazonaws.com
|
|
||||||
Action: sts:AssumeRole
|
|
||||||
Policies:
|
|
||||||
- PolicyName: InvokeLambda
|
|
||||||
PolicyDocument:
|
|
||||||
Version: '2012-10-17'
|
|
||||||
Statement:
|
|
||||||
- Effect: Allow
|
|
||||||
Action:
|
|
||||||
- lambda:InvokeFunction
|
|
||||||
Resource:
|
|
||||||
- !GetAtt HelloLambda.Arn
|
|
||||||
|
|
||||||
HelloLambda:
|
|
||||||
Type: AWS::Lambda::Function
|
|
||||||
Properties:
|
|
||||||
Role: !GetAtt HelloLambdaRole.Arn # TODO
|
|
||||||
Handler: index.handleHttpRequest
|
|
||||||
Runtime: nodejs12.x
|
|
||||||
Environment:
|
|
||||||
Variables:
|
|
||||||
HELLO_DB: !Sub "arn:aws:dynamodb:${AWS::Region}:*:table/${HelloTable}"
|
|
||||||
Code:
|
|
||||||
ZipFile: |
|
|
||||||
exports.handlers = function(event, context) {}
|
|
||||||
HelloLambdaRole: # -> AppAPIRole
|
|
||||||
Type: AWS::IAM::Role
|
|
||||||
Properties:
|
|
||||||
AssumeRolePolicyDocument:
|
|
||||||
Version: '2012-10-17'
|
|
||||||
Statement:
|
|
||||||
- Effect: Allow
|
|
||||||
Principal:
|
|
||||||
Service: lambda.amazonaws.com
|
|
||||||
Action: sts:AssumeRole
|
|
||||||
ManagedPolicyArns:
|
|
||||||
- !Ref BaseLambdaExecutionPolicy
|
|
||||||
Policies:
|
|
||||||
- PolicyName: getHello
|
|
||||||
PolicyDocument:
|
|
||||||
Version: '2012-10-17'
|
|
||||||
Statement:
|
|
||||||
- Effect: Allow
|
|
||||||
Action:
|
|
||||||
- dynamodb:GetItem
|
|
||||||
Resource: !Sub "arn:aws:dynamodb:${AWS::Region}:*:table/${HelloTable}"
|
|
||||||
- PolicyName: putHello
|
|
||||||
PolicyDocument:
|
|
||||||
Version: '2012-10-17'
|
|
||||||
Statement:
|
|
||||||
- Effect: Allow
|
|
||||||
Action:
|
|
||||||
- dynamodb:PutItem
|
|
||||||
Resource: !Sub "arn:aws:dynamodb:${AWS::Region}:*:table/${HelloTable}"
|
|
||||||
Reference in New Issue
Block a user