Skip to content

Commit 5fa2dec

Browse files
committed
api code complete
1 parent fdb90d3 commit 5fa2dec

File tree

11 files changed

+310
-45
lines changed

11 files changed

+310
-45
lines changed

.funcignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
*.js.map
2+
*.ts
3+
.git*
4+
.vscode
5+
local.settings.json
6+
test
7+
tsconfig.json

.vscode/extensions.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"recommendations": [
3+
"ms-azuretools.vscode-azurefunctions"
4+
]
5+
}

.vscode/launch.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"version": "0.2.0",
3+
"configurations": [
4+
{
5+
"name": "Attach to Node Functions",
6+
"type": "node",
7+
"request": "attach",
8+
"port": 9229,
9+
"preLaunchTask": "func: host start"
10+
}
11+
]
12+
}

.vscode/settings.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"azureFunctions.deploySubpath": ".",
3+
"azureFunctions.postDeployTask": "npm install",
4+
"azureFunctions.projectLanguage": "JavaScript",
5+
"azureFunctions.projectRuntime": "~2",
6+
"debug.internalConsoleOptions": "neverOpen",
7+
"azureFunctions.preDeployTask": "npm prune"
8+
}

.vscode/tasks.json

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"version": "2.0.0",
3+
"tasks": [
4+
{
5+
"type": "func",
6+
"command": "host start",
7+
"problemMatcher": "$func-watch",
8+
"isBackground": true,
9+
"dependsOn": "npm install"
10+
},
11+
{
12+
"type": "shell",
13+
"label": "npm install",
14+
"command": "npm install"
15+
},
16+
{
17+
"type": "shell",
18+
"label": "npm prune",
19+
"command": "npm prune --production",
20+
"problemMatcher": []
21+
}
22+
]
23+
}

README.md

Lines changed: 123 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,145 @@
1-
# Project Name
1+
---
2+
page_type: sample
3+
languages:
4+
- nodejs
5+
- javascript
6+
- tsql
7+
- sql
8+
products:
9+
- azure
10+
- vs-code
11+
- azure-sql-database
12+
- azure-functions
13+
description: "Creating a modern REST API with Python and Azure SQL, using Flask and Visual Studio Code"
14+
urlFragment: "azure-sql-db-node-rest-api"
15+
---
216

3-
(short, 1-3 sentenced, description of the project)
17+
# Creating a REST API with Azure Functions, Node and Azure SQL
418

5-
## Features
19+
![License](https://img.shields.io/badge/license-MIT-green.svg)
620

7-
This project framework provides the following features:
21+
<!--
22+
Guidelines on README format: https://review.docs.microsoft.com/help/onboard/admin/samples/concepts/readme-template?branch=master
823
9-
* Feature 1
10-
* Feature 2
11-
* ...
24+
Guidance on onboarding samples to docs.microsoft.com/samples: https://review.docs.microsoft.com/help/onboard/admin/samples/process/onboarding?branch=master
1225
13-
## Getting Started
26+
Taxonomies for products and languages: https://review.docs.microsoft.com/new-hope/information-architecture/metadata/taxonomies?branch=master
27+
-->
1428

15-
### Prerequisites
29+
Thanks to native JSON support, creating a serverless REST API with Azure Functions, Azure SQL and Node is really a matter of a few lines of code. Take a look at `customer/index.js` to see how easy it is!
1630

17-
(ideally very short, if any)
31+
Wondering what's the magic behind? Azure Functions takes care of running the NodeJS code, so all is needed is to get the incoming HTTP request, handle it, send the data as we receive it - a JSON - to Azure SQL and we're done. Thanks to the [native JSON support that Azure SQL provides](https://docs.microsoft.com/en-us/azure/sql-database/sql-database-json-features) does all the heavy lifting so sending data back and forth to the database is as easy as sending a JSON message.
1832

19-
- OS
20-
- Library version
21-
- ...
33+
## Install Sample Database
2234

23-
### Installation
35+
In order to run this sample, the WideWorldImporters database is needed. Install WideWorldImporters sample database:
2436

25-
(ideally very short)
37+
[Restore WideWorldImporters Database](https://github.com/yorek/azure-sql-db-samples#restore-wideworldimporters-database)
2638

27-
- npm install [package name]
28-
- mvn install
29-
- ...
39+
## Add Database Objects
3040

31-
### Quickstart
32-
(Add steps to get up and running quickly)
41+
Once the sample database has been installed, you need to add some stored procedure that will called from Python. The SQL code is available here:
3342

34-
1. git clone [repository clone url]
35-
2. cd [respository name]
36-
3. ...
43+
`./sql/WideWorldImportersUpdates.sql`
3744

45+
If you need any help in executing the SQL script, you can find a Quickstart here: [Quickstart: Use Azure Data Studio to connect and query Azure SQL database](https://docs.microsoft.com/en-us/sql/azure-data-studio/quickstart-sql-database)
3846

39-
## Demo
47+
## Run sample locally
4048

41-
A demo app is included to show how to use the project.
49+
Make sure you add the information needed to connect to the desired Azure SQL database in the `local.settings.json`. Create it in the root folder of the sample using the `.template` file, if there isn't one already. After editing the file should look like the following:
4250

43-
To run the demo, follow these steps:
51+
```json
52+
{
53+
"IsEncrypted": false,
54+
"Values": {
55+
"FUNCTIONS_WORKER_RUNTIME": "node",
56+
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
57+
"db_server": "<server>.database.windows.net",
58+
"db_database": "<database>",
59+
"db_user": "NodeFuncApp",
60+
"db_password": "aN0ThErREALLY#$%TRONGpa44w0rd!"
61+
}
62+
}
63+
```
4464

45-
(Add steps to start up the demo)
65+
where `<server>` and `<database>` have been replaced with the correct values for your environment. Once done that, start local Azure Function host with
4666

47-
1.
48-
2.
49-
3.
67+
```bash
68+
func start
69+
```
5070

51-
## Resources
71+
if you are using [Azure Functions Core Tools](https://www.npmjs.com/package/azure-functions-core-tools) or using [Visual Studio Code Azure Function extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurefunctions)
5272

53-
(Any additional resources or related projects)
73+
For more info on other options to run Azure Function locally look here:
5474

55-
- Link to supporting information
56-
- Link to similar sample
57-
- ...
75+
[Code and test Azure Functions locally](https://docs.microsoft.com/en-us/azure/azure-functions/functions-develop-local)
76+
77+
Once the Azure Function HTTP is up and running you'll see something like
78+
79+
```text
80+
Now listening on: http://0.0.0.0:7071
81+
Application started. Press Ctrl+C to shut down.
82+
83+
Http Functions:
84+
85+
customer: [GET,PUT,PATCH,DELETE] http://localhost:7071/api/customer/{id:int?}
86+
```
87+
88+
Using a REST Client (like [Insomnia](https://insomnia.rest/), [Postman](https://www.getpostman.com/) or curl), you can now call your API, for example:
89+
90+
```bash
91+
curl -X GET http://localhost:7071/customer/123
92+
```
93+
94+
and you'll get info on Customer 123:
95+
96+
```json
97+
[
98+
{
99+
"CustomerID": 123,
100+
"CustomerName": "Tailspin Toys (Roe Park, NY)",
101+
"PhoneNumber": "(212) 555-0100",
102+
"FaxNumber": "(212) 555-0101",
103+
"WebsiteURL": "http://www.tailspintoys.com/RoePark",
104+
"Delivery": {
105+
"AddressLine1": "Shop 219",
106+
"AddressLine2": "528 Persson Road",
107+
"PostalCode": "90775"
108+
}
109+
}
110+
]
111+
```
112+
113+
Check out more samples to test all implemented verbs here:
114+
115+
[cUrl Samples](./sample-usage.md)
116+
117+
## Debug from Visual Studio Code
118+
119+
Debugging from Visual Studio Code is fully supported, thanks to the [Visual Studio Code Azure Function extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurefunctions
120+
121+
## Deploy to Azure
122+
123+
TDB
124+
125+
## Connection Resiliency
126+
127+
TDB
128+
129+
## Learn more
130+
131+
TDB
132+
133+
## Contributing
134+
135+
This project welcomes contributions and suggestions. Most contributions require you to agree to a
136+
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
137+
the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
138+
139+
When you submit a pull request, a CLA bot will automatically determine whether you need to provide
140+
a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
141+
provided by the bot. You will only need to do this once across all repos using our CLA.
142+
143+
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
144+
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
145+
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.

azure-deploy.sh

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#!/bin/bash
2+
3+
set -euo pipefail
4+
5+
# Make sure these values are correct for your environment
6+
resourceGroup="dm-api-03"
7+
appName="dm-api-03"
8+
location="WestUS2"
9+
10+
# Change this if you are using your own github repository
11+
gitSource="https://github.com/Azure-Samples/azure-sql-db-node-rest-api.git"
12+
13+
# Make sure variables are sent in local.settings.json
14+
if [[ -z "${SQLAZURECONNSTR_WWIF:-}" ]]; then
15+
echo "Plase export Azure SQL connection string:";
16+
echo "export SQLAZURECONNSTR_WWIF=\"your-connection-string-here\"";
17+
exit 1;
18+
fi
19+
20+
echo "Creating Resource Group...";
21+
az group create \
22+
-n $resourceGroup \
23+
-l $location
24+
25+
echo "Creating Application Service Plan...";
26+
az appservice plan create \
27+
-g $resourceGroup \
28+
-n "linux-plan" \
29+
--sku B1 \
30+
--is-linux
31+
32+
echo "Creating Application Insight..."
33+
az resource create \
34+
-g $resourceGroup \
35+
-n $appName-ai \
36+
--resource-type "Microsoft.Insights/components" \
37+
--properties '{"Application_Type":"web"}'
38+
39+
echo "Reading Application Insight Key..."
40+
aikey=`az resource show -g $resourceGroup -n $appName-ai --resource-type "Microsoft.Insights/components" --query properties.InstrumentationKey -o tsv`
41+
42+
echo "Creating Web Application...";
43+
az webapp create \
44+
-g $resourceGroup \
45+
-n $appName \
46+
--plan "linux-plan" \
47+
--runtime "PYTHON|3.7" \
48+
--deployment-source-url $gitSource \
49+
--deployment-source-branch master
50+
51+
echo "Configuring Connection String...";
52+
az webapp config connection-string set \
53+
-g $resourceGroup \
54+
-n $appName \
55+
--settings WWIF="$SQLAZURECONNSTR_WWIF" \
56+
--connection-string-type=SQLAzure
57+
58+
echo "Configuring Application Insights...";
59+
az webapp config appsettings set \
60+
-g $resourceGroup \
61+
-n $appName \
62+
--settings APPINSIGHTS_KEY="$aikey"
63+
64+
echo "Done."

customer/function.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
"name": "req",
88
"methods": [
99
"get",
10-
"post"
10+
"put",
11+
"patch",
12+
"delete"
1113
],
1214
"route": "customer/{id:int?}"
1315
},

customer/index.js

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const executeSQL = (context, verb, entity, payload) => {
2626
// Create the command to be executed
2727
const request = new Request(`web.${verb}_${entity}`, (err) => {
2828
if (err) {
29-
context.log.error(err);
29+
context.log.error(err);
3030
context.res.status = 500;
3131
context.res.body = "Error executing T-SQL command";
3232
} else {
@@ -36,7 +36,8 @@ const executeSQL = (context, verb, entity, payload) => {
3636
}
3737
context.done();
3838
});
39-
request.addParameter('Json', TYPES.NVarChar, paramPayload, Infinity);
39+
if (payload)
40+
request.addParameter('Json', TYPES.NVarChar, paramPayload, Infinity);
4041

4142
// Handle 'connect' event
4243
connection.on('connect', err => {
@@ -74,19 +75,26 @@ module.exports = function (context, req) {
7475
if (req.params.id) {
7576
entity = "customer"
7677
payload = { "CustomerID": req.params.id };
78+
} else {
79+
entity = "customers"
7780
}
7881
break;
79-
case "post":
80-
payload = req.body;
82+
case "patch":
83+
entity = "customer"
84+
payload = req.body;
85+
if (req.params.id)
86+
payload.CustomerID = req.params.id;
8187
break;
8288
case "put":
83-
payload = {
84-
"id": req.params.id,
85-
"todo": req.body
86-
};
89+
entity = "customer"
90+
payload = req.body;
8791
break;
8892
case "delete":
89-
payload = { "id": req.params.id };
93+
entity = "customer"
94+
if (req.params.id) {
95+
entity = "customer"
96+
payload = { "CustomerID": req.params.id };
97+
}
9098
break;
9199
}
92100

local.settings.json.template

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"IsEncrypted": false,
3+
"Values": {
4+
"FUNCTIONS_WORKER_RUNTIME": "node",
5+
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
6+
"db_server": "<server>.database.windows.net",
7+
"db_database": "<database>",
8+
"db_user": "NodeFuncApp",
9+
"db_password": "aN0ThErREALLY#$%TRONGpa44w0rd!"
10+
}
11+
}

0 commit comments

Comments
 (0)