Implement serverless pun api
This commit is contained in:
parent
a21be0fa91
commit
8233572d2b
8 changed files with 2732 additions and 0 deletions
3
.env.sample
Normal file
3
.env.sample
Normal file
|
@ -0,0 +1,3 @@
|
|||
export AWS_CERTIFICATE=arn:aws:acm:REGION:ACCOUNT:certificate/HASH
|
||||
export DNS_ZONE=example.com.
|
||||
export DOMAIN=puns.example.com
|
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
node_modules/
|
||||
.serverless/
|
||||
.env
|
||||
.env.production
|
4
Makefile
Normal file
4
Makefile
Normal file
|
@ -0,0 +1,4 @@
|
|||
yarnbin = $(shell yarn bin)
|
||||
|
||||
deploy:
|
||||
sh -c "source .env.production; $(yarnbin)/serverless deploy --stage production"
|
20
README.md
Normal file
20
README.md
Normal file
|
@ -0,0 +1,20 @@
|
|||
# punaday-api
|
||||
|
||||
JSON version of http://www.punoftheday.com/
|
||||
|
||||
## Description
|
||||
|
||||
Server that takes Pun of the Day puns and converts it into JSON. Currently
|
||||
living as a serverless application in AWS Lamda. It is frontended by AWS
|
||||
Cloudfront because AWS Cloudformation does not yet have resources for AWS API
|
||||
Gateway domains. This script will also create a DNS record to point at the
|
||||
AWS Cloudfront Distribution.
|
||||
|
||||
## Usage
|
||||
|
||||
* `cp .env.sample .env.production`
|
||||
* `AWS_CERTIFICATE`: arn to aws certificate that you generated for a domain
|
||||
* `DNS_ZONE`: Route 53 zone name (ex. `example.com.`)
|
||||
* `DOMAIN`: Route 53 domain (ex. `puns.example.com`)
|
||||
* Set AWS credentials via environment or credential file
|
||||
* `make`
|
11
package.json
Normal file
11
package.json
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"devDependencies": {
|
||||
"babel-preset-es2015": "^6.24.0",
|
||||
"serverless": "^1.9.0",
|
||||
"serverless-offline": "^3.10.3",
|
||||
"serverless-plugin-optimize": "^1.0.0-rc.15"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.15.3"
|
||||
}
|
||||
}
|
82
serverless.yml
Normal file
82
serverless.yml
Normal file
|
@ -0,0 +1,82 @@
|
|||
service: punaday-api
|
||||
|
||||
provider:
|
||||
name: aws
|
||||
runtime: nodejs4.3
|
||||
memorySize: 128
|
||||
|
||||
plugins:
|
||||
- serverless-plugin-optimize
|
||||
- serverless-offline
|
||||
|
||||
package:
|
||||
individually: true
|
||||
|
||||
resources:
|
||||
Resources:
|
||||
CloudfrontDistribution:
|
||||
Type: AWS::CloudFront::Distribution
|
||||
Properties:
|
||||
DistributionConfig:
|
||||
Aliases:
|
||||
- ${env:DOMAIN}
|
||||
Origins:
|
||||
- DomainName: { "Fn::Join": [".", [ { "Ref": "ApiGatewayRestApi" }, "execute-api", { "Ref": "AWS::Region" }, "amazonaws.com"] ] }
|
||||
OriginPath: "/production"
|
||||
Id: APIGW
|
||||
CustomOriginConfig:
|
||||
HTTPSPort: 443
|
||||
OriginProtocolPolicy: https-only
|
||||
DefaultCacheBehavior:
|
||||
AllowedMethods:
|
||||
- HEAD
|
||||
- DELETE
|
||||
- POST
|
||||
- GET
|
||||
- OPTIONS
|
||||
- PUT
|
||||
- PATCH
|
||||
TargetOriginId: APIGW
|
||||
ForwardedValues:
|
||||
QueryString: true
|
||||
Cookies:
|
||||
Forward: none
|
||||
ViewerProtocolPolicy: redirect-to-https
|
||||
DefaultTTL: 0
|
||||
Enabled: true
|
||||
ViewerCertificate:
|
||||
AcmCertificateArn: ${env:AWS_CERTIFICATE}
|
||||
SslSupportMethod: sni-only
|
||||
Route53RecordSet:
|
||||
Type: AWS::Route53::RecordSetGroup
|
||||
Properties:
|
||||
HostedZoneName: ${env:DNS_ZONE}
|
||||
RecordSets:
|
||||
- Name: ${env:DOMAIN}
|
||||
Type: A
|
||||
AliasTarget:
|
||||
DNSName: { "Fn::GetAtt" : [ "CloudfrontDistribution", "DomainName"] }
|
||||
HostedZoneId: Z2FDTNDATAQYW2 # always use for cloudfront
|
||||
|
||||
functions:
|
||||
punsShow:
|
||||
handler: src/puns/show.show
|
||||
events:
|
||||
- http:
|
||||
path: puns/{id}
|
||||
method: get
|
||||
cors: true
|
||||
punsToday:
|
||||
handler: src/puns/show.today
|
||||
events:
|
||||
- http:
|
||||
path: puns/today
|
||||
method: get
|
||||
cors: true
|
||||
punsRandom:
|
||||
handler: src/puns/show.random
|
||||
events:
|
||||
- http:
|
||||
path: puns/random
|
||||
method: get
|
||||
cors: true
|
53
src/puns/show.js
Normal file
53
src/puns/show.js
Normal file
|
@ -0,0 +1,53 @@
|
|||
const axios = require('axios')
|
||||
|
||||
const PUN_BASE = 'http://www.punoftheday.com'
|
||||
|
||||
module.exports.today = ((event, context, callback) => {
|
||||
respondWithPunFrom(PUN_BASE, callback)
|
||||
})
|
||||
|
||||
module.exports.random = ((event, context, callback) => {
|
||||
respondWithPunFrom(`${PUN_BASE}/cgi-bin/randompun.pl`, callback)
|
||||
})
|
||||
|
||||
module.exports.show = ((event, context, callback) => {
|
||||
const id = event.pathParameters.id
|
||||
|
||||
respondWithPunFrom(`${PUN_BASE}/pun/${id}`, callback)
|
||||
})
|
||||
|
||||
function respondWithPunFrom(url, callback) {
|
||||
return axios.get(url)
|
||||
.then(response => {
|
||||
const pun = parsePun(response.data)
|
||||
|
||||
callback(null, punResponse(pun))
|
||||
})
|
||||
.catch(error => {
|
||||
callback(null, errorResponse())
|
||||
})
|
||||
}
|
||||
|
||||
function parsePun(html) {
|
||||
const punMatches = html.match(/<p>(.*)<\/p>/)
|
||||
const text = punMatches[1].replace('“', '').replace('”', '')
|
||||
const idMatches = html.match(/name="PunID" value="(\d+)"/)
|
||||
const id = idMatches[1]
|
||||
const urlMatches = html.match(/class="fb-share-button" data-href="(.*)" d/)
|
||||
const url = urlMatches[1]
|
||||
|
||||
return { id, text, url }
|
||||
}
|
||||
|
||||
function punResponse (pun) {
|
||||
delete pun['id']
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
body: JSON.stringify(pun)
|
||||
}
|
||||
}
|
||||
|
||||
function errorResponse () {
|
||||
return { statusCode: 500 }
|
||||
}
|
Loading…
Reference in a new issue