forked from CodeGenieApp/serverless-express
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add support for azure function v4 event source (CodeGenieApp#529)
* feat: add support for azure function v4 event source * docs: add azure http function v4 support to README.md * fix: npm package out of sync issue Co-authored-by: brett-vendia <72168202+brett-vendia@users.noreply.github.com>
- Loading branch information
1 parent
f7f3f6c
commit 503c9d0
Showing
21 changed files
with
1,787 additions
and
16 deletions.
There are no files selected for viewing
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
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
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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
const path = require('path') | ||
const express = require('express') | ||
const bodyParser = require('body-parser') | ||
const cors = require('cors') | ||
const compression = require('compression') | ||
const { getCurrentInvoke } = require('../../../src/index') // require('@vendia/serverless-express') | ||
const ejs = require('ejs').__express | ||
const app = express() | ||
const router = express.Router() | ||
|
||
app.set('view engine', 'ejs') | ||
app.engine('.ejs', ejs) | ||
|
||
router.use(compression()) | ||
router.use(cors()) | ||
router.use(bodyParser.json()) | ||
router.use(bodyParser.urlencoded({ extended: true })) | ||
|
||
// NOTE: tests can't find the views directory without this | ||
app.set('views', path.join(__dirname, 'views')) | ||
|
||
router.get('/api', (req, res) => { | ||
const currentInvoke = getCurrentInvoke() | ||
const { event = {} } = currentInvoke | ||
const { requestContext = {} } = event | ||
const { domainName = 'localhost:7071' } = requestContext | ||
const apiUrl = `https://${domainName}` | ||
res.render('index', { apiUrl }) | ||
}) | ||
|
||
router.get('/api/vendia', (req, res) => { | ||
res.sendFile(path.join(__dirname, 'vendia-logo.png')) | ||
}) | ||
|
||
router.get('/api/users', (req, res) => { | ||
res.json(users) | ||
}) | ||
|
||
router.get('/api/users/:userId', (req, res) => { | ||
const user = getUser(req.params.userId) | ||
|
||
if (!user) return res.status(404).json({}) | ||
|
||
return res.json(user) | ||
}) | ||
|
||
router.post('/api/users', (req, res) => { | ||
const user = { | ||
id: ++userIdCounter, | ||
name: req.body.name | ||
} | ||
users.push(user) | ||
res.status(201).json(user) | ||
}) | ||
|
||
router.put('/api/users/:userId', (req, res) => { | ||
const user = getUser(req.params.userId) | ||
|
||
if (!user) return res.status(404).json({}) | ||
|
||
user.name = req.body.name | ||
res.json(user) | ||
}) | ||
|
||
router.delete('/api/users/:userId', (req, res) => { | ||
const userIndex = getUserIndex(req.params.userId) | ||
|
||
if (userIndex === -1) return res.status(404).json({}) | ||
|
||
users.splice(userIndex, 1) | ||
res.json(users) | ||
}) | ||
|
||
router.get('/api/cookie', (req, res) => { | ||
res.cookie('Foo', 'bar') | ||
res.cookie('Fizz', 'buzz') | ||
res.json({}) | ||
}) | ||
|
||
const getUser = (userId) => users.find(u => u.id === parseInt(userId)) | ||
const getUserIndex = (userId) => users.findIndex(u => u.id === parseInt(userId)) | ||
|
||
// Ephemeral in-memory data store | ||
const users = [{ | ||
id: 1, | ||
name: 'Joe' | ||
}, { | ||
id: 2, | ||
name: 'Jane' | ||
}] | ||
let userIdCounter = users.length | ||
|
||
// The serverless-express library creates a server and listens on a Unix | ||
// Domain Socket for you, so you can remove the usual call to app.listen. | ||
// app.listen(3000) | ||
app.use('/', router) | ||
|
||
// Export your express server so you can import it in the lambda function. | ||
module.exports = app |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"bindings": [ | ||
{ | ||
"authLevel": "anonymous", | ||
"type": "httpTrigger", | ||
"direction": "in", | ||
"name": "req", | ||
"route": "{*segments}" | ||
}, | ||
{ | ||
"type": "http", | ||
"direction": "out", | ||
"name": "$return" | ||
} | ||
] | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
const serverlessExpress = require('../../../src/index') // require('@vendia/serverless-express') | ||
const app = require('./app') | ||
const cachedServerlessExpress = serverlessExpress({ app }) | ||
|
||
module.exports = async function (context, req) { | ||
return cachedServerlessExpress(context, req) | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
115 changes: 115 additions & 0 deletions
115
examples/azure-http-function-v4/HttpExample/views/index.ejs
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
|
||
<head> | ||
<title>My Serverless Application</title> | ||
<style> | ||
body { | ||
width: 650px; | ||
margin: auto; | ||
} | ||
h1 { | ||
text-align: center; | ||
} | ||
.resources>h2 { | ||
margin-bottom: 0; | ||
} | ||
.resource>h3, | ||
.resource>p { | ||
display: inline-block; | ||
margin-bottom: 0.5rem; | ||
} | ||
.resource>code { | ||
display: block; | ||
background-color: #eff0f1; | ||
color: #393318; | ||
padding: 5px; | ||
font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, sans-serif; | ||
white-space: nowrap; | ||
overflow-x: auto; | ||
} | ||
.vendia-logo { | ||
display: block; | ||
width: 10rem; | ||
margin: auto; | ||
} | ||
form { | ||
margin-bottom: 1rem; | ||
} | ||
.form-group { | ||
padding-bottom: 1rem; | ||
} | ||
label { | ||
display: block; | ||
} | ||
</style> | ||
</head> | ||
|
||
<body> | ||
<h1>My Serverless Application</h1><img class="vendia-logo" src="/api/vendia"> | ||
<p>Welcome to your Azure Function serverless application. This example application has several resources configured for you to explore. State is stored in memory in a given container, and is therefore ephemeral.</p> | ||
<section class="resources"> | ||
<h2>Resources</h2> | ||
<section class="resource"> | ||
<h3><a class="resource-example-link" href="/api/users">GET /users</a></h3> | ||
<p> Returns a list of all users.</p><code>curl <span><%= apiUrl %></span>/users -H 'accept: application/json'</code> | ||
</section> | ||
<section class="resource"> | ||
<h3>POST /users</h3> | ||
<p> Creates a new user.</p><code>curl <span><%= apiUrl %></span>/api/users -X POST -d '{"name":"Sam"}' -H 'accept: application/json'</code> | ||
</section> | ||
<section class="resource"> | ||
<h3><a class="resource-example-link" href="/api/users/1">GET /users/:userId</a></h3> | ||
<p> Returns a single user.</p><code>curl <span><%= apiUrl %></span>/api/users/1 -H 'accept: application/json'</code> | ||
</section> | ||
<section class="resource"> | ||
<h3>PUT /users/:userId</h3> | ||
<p> Updates an existing user.</p><code>curl <span><%= apiUrl %></span>/api/users/1 -X PUT -d '{"name":"Samantha"}' -H 'accept: application/json'</code> | ||
</section> | ||
<section class="resource"> | ||
<h3>DELETE /users/:userId</h3> | ||
<p> Deletes an existing user.</p><code>curl <span><%= apiUrl %></span>/api/users/1 -X DELETE -H 'accept: application/json'</code> | ||
</section> | ||
</section> | ||
<section class="form"> | ||
<h2>Form</h2> | ||
<p>Experiment with POST and PUT via the form below. Leave the id empty to create a new user (POST) or enter an id to update a user's name (PUT).</p> | ||
<form> | ||
<div class="form-group"><label for="idField">user id</label><input type="text" name="id" id="idField" placeholder="optional"></div> | ||
<div class="form-group"><label for="nameField">name</label><input type="text" name="name" id="nameField"></div><input type="submit"> | ||
</form> | ||
</section> | ||
<script> | ||
var form = document.querySelector('form') | ||
form.addEventListener('submit', function(event) { | ||
event.preventDefault() | ||
var id = document.getElementById('idField').value | ||
var name = document.getElementById('nameField').value | ||
var endpoint = id ? 'users/' + id : 'users' | ||
if (!window.fetch) { | ||
alert('Your browser does not have fetch support, which this demo uses. Try again in a modern browser (https://caniuse.com/fetch) or modify the example to use an alternate approach (e.g. XMLHttpRequest or your library of choice.)') | ||
} | ||
return fetch(endpoint, { | ||
method: id ? 'PUT' : 'POST', | ||
headers: { | ||
'content-type': 'application/json' | ||
}, | ||
body: JSON.stringify({ | ||
name: name | ||
}) | ||
}) | ||
}) | ||
</script> | ||
</body> | ||
|
||
</html> |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# Example - Azure Function HTTP v4 | ||
|
||
This example uses the local tools provided by Microsoft to simulate an Azure Function environment. This means there is no Azure Account required to run this example. | ||
|
||
## Run local requirements | ||
|
||
These prerequisites are required to run and debug your functions locally. | ||
|
||
- Visual Studio Code | ||
- Visual Studio Code - Azure Functions extension | ||
- Azure Functions Core Tools (`npm install -g azure-functions-core-tools@4 --unsafe-perm true`) | ||
- Node.js | ||
|
||
_For further information on how to run an Azure Function locally please check [Develop Azure Functions by using Visual Studio Code](https://docs.microsoft.com/en-us/azure/azure-functions/functions-develop-vs-code?tabs=nodejs)._ | ||
|
||
|
||
## Installation & Usage | ||
|
||
After all requirements are fulfilled you can install all dependencies for the `azure-http-function-v4` with npm. | ||
|
||
```bash | ||
cd examples/azure-http-function-v4 | ||
npm install | ||
npm run start | ||
``` | ||
|
||
|
||
|
||
After you run the last command you should see an output like this: | ||
|
||
```bash | ||
Azure Functions Core Tools | ||
Core Tools Version: 4.0.4590 | ||
Function Runtime Version: 4.5.2.18383 | ||
|
||
|
||
Functions: | ||
|
||
HttpExample: http://localhost:7071/api/{*segments} | ||
``` | ||
|
||
Now you can navigate to `http://localhost:7071/api/` to display the `My Serverless Application` page. |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"version": "2.0", | ||
"logging": { | ||
"applicationInsights": { | ||
"samplingSettings": { | ||
"isEnabled": true, | ||
"excludedTypes": "Request" | ||
} | ||
} | ||
}, | ||
"extensionBundle": { | ||
"id": "Microsoft.Azure.Functions.ExtensionBundle", | ||
"version": "[3.3.0, 4.0.0)" | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"IsEncrypted": false, | ||
"Values": { | ||
"FUNCTIONS_WORKER_RUNTIME": "node", | ||
"AzureWebJobsStorage": "", | ||
"FUNCTIONS_EXTENSION_VERSION": "~4" | ||
} | ||
} |
Oops, something went wrong.