Skip to content

Commit

Permalink
Merge pull request #83 from pharindoko/feature/generate-swagger
Browse files Browse the repository at this point in the history
Feature/generate swagger
  • Loading branch information
pharindoko authored Aug 24, 2019
2 parents 45203ec + f4b476c commit c8c0242
Show file tree
Hide file tree
Showing 19 changed files with 955 additions and 106 deletions.
6 changes: 3 additions & 3 deletions .env.sample
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
S3FILE=db.json
S3BUCKET=json-serverless-dev
READONLY=false
S3File=db.json
S3Bucket=json-serverless-dev
readOnly=false
193 changes: 130 additions & 63 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,46 +9,53 @@
- [Develop locally with cloud resources](#develop-locally-with-cloud-resources)
- [Diagnose issues](#diagnose-issues)

## Architecture

![Architecture](docs/json-serverless.png)

## Features

- Development:
- Easily setup routes and resources for the REST Api via json file. [(via json-server)](https://github.com/typicode/json-server)
- This solution written in **NodeJS** can be easily extended for additional enhanced scenarios
- adding user authentication
- own custom domain
- additional routes etc.
- Develop and test solution locally in Visual Studio Code
- Security: This Api is secured via API Key and https by default.
- Easily setup routes and resources for the REST Api via json file. [(via json-server)](https://github.com/typicode/json-server)
- **New:** Added Swagger UI support
- Deployment:
- Deployed in AWS cloud within Minutes by a single command
- Almost **zero costs** (First million requests for Lambda are free)
- Less maintenance as the deployed solution runs **serverless**
- Security:
- Secured with https by default.
- Optional: Use a generated API Key
- Customization:
- This solution written in **NodeJS** can be easily extended for additional enhanced scenarios
- adding user authentication
- own custom domain
- additional routes etc.
- Develop and debug solution locally in Visual Studio Code

## Quickstart

##### 1. Clone Solution
### 1. Clone Solution

```bash
git clone https://github.com/pharindoko/json-serverless.git
git clone https://github.com/pharindoko/json-serverless.git
cd json-serverless
```

##### 2. Install dependencies
### 2. Install dependencies

```bash
npm install -g serverless
npm i
```

##### 3. Verify AWS Access / Credentials
### 3. Verify AWS Access / Credentials

=> You need to have access to AWS to upload the solution.

```bash
aws sts get-caller-identity
```

##### 4. Update db.json file in root directory
### 4. Update db.json file in root directory

- Childproperties are the REST endpoints you create
- Samplefile: Routes marked **bold**
Expand All @@ -61,8 +68,7 @@ aws sts get-caller-identity
}
</code></pre>

##### 5. Deploy via Serverless Framework

### 5. Deploy via Serverless Framework

```bash
# set --stage parameter for different stages
Expand All @@ -72,7 +78,7 @@ serverless deploy --stage dev
- serverless-webpack is used
- the build will be triggered automatically

##### 6. When the deployment with serverless framework was successful you can see following output
### 6. When the deployment with serverless framework was successful you can see following output

<pre>
<code>
Expand All @@ -82,9 +88,9 @@ stage: dev
region: eu-central-1
stack: serverless-json-server-dev
api keys:
serverless-json-server.dev: <b>{API - KEY}</b>
serverless-json-server.dev: <b>{API-KEY}</b>
endpoints:
ANY - <b>https://xxxxxx.execute-api.eu-central-1.amazonaws.com/dev/</b>
ANY - <b>https://xxxxxx.execute-api.eu-central-1.amazonaws.com/dev/ <== {ENDPOINTURL}</b>
ANY - https://xxxxxxx.eu-central-1.amazonaws.com/dev/{proxy+}
functions:
app: serverless-json-server-dev-app
Expand All @@ -93,45 +99,40 @@ layers:
Serverless: Removing old service artifacts from S3...
</pre></code>

##### 7. Test your Api
### 7. Test your Api

#### With Swagger

Open the {ENDPOINTURL}: https://xxxxxx.execute-api.eu-central-1.amazonaws.com/dev/ that you received as output

##### With Curl
**MIND**: If you have set enableApiKeyAuth to true => [SwaggerUI](#Cannot-use-Swagger-UI-when-enableApiKeyAuth-is-true)
)

#### With Curl

1. replace the url with the url provided by serverless (see above)
2. replace the {API - KEY} with the key you get from serverless (see above)
2. replace the {API-KEY} with the key you get from serverless (see above)
3. replace {route} at the end of the url e.g. with posts (default value)

Default Schema:

```bash
Default route is posts: (see db.json)
curl -H "x-api-key: {API - KEY}" -H "Content-Type: application/json" https://xxxxxx.execute-api.eu-central-1.amazonaws.com/dev/posts
curl -H "Content-Type: application/json" https://xxxxxx.execute-api.eu-central-1.amazonaws.com/dev/api/posts

#or another route given in db.json file
curl -H "x-api-key: {API - KEY}" -H "Content-Type: application/json" https://xxxxxx.execute-api.eu-central-1.amazonaws.com/dev/{route}
```
# or another route given in db.json file
curl -H "Content-Type: application/json" https://xxxxxx.execute-api.eu-central-1.amazonaws.com/dev/api/{route}

##### With Postman
# with enableApiKeyAuth=true
curl -H "x-api-key: {API-KEY}" -H "Content-Type: application/json" https://xxxxxx.execute-api.eu-central-1.amazonaws.com/dev/api/{route}

- Create a new GET Request and add these values to the header section

|Key| Value|
|---|---|
|x-api-key | {API - KEY}|
|Content-Type | application/json|

- Enter as Url the endpoints url

```bash
https://xxxxxx.execute-api.eu-central-1.amazonaws.com/dev/{route}
# e.g. default value: https://xxxxxx.execute-api.eu-central-1.amazonaws.com/dev/posts
```

What`s my {route} ? -> see [json-server documentation](https://github.com/typicode/json-server)

## Customization

#### Update content of db.json
### Update content of db.json

1. update local db.json file in root directory with new values
2. re-deploy the stack via serverless framework
Expand All @@ -141,10 +142,15 @@ What`s my {route} ? -> see [json-server documentation](https://github.com/typico
```

3. delete db.json file in S3 Bucket
4. Make a GET request against the root url https://xxxxxx.execute-api.eu-central-1.amazonaws.com/dev/
4. Make a GET request against the root url https://xxxxxx.execute-api.eu-central-1.amazonaws.com/dev/api

```bash
curl -H "x-api-key: {API - KEY}" -H "Content-Type: application/json" https://xxxxxx.execute-api.eu-central-1.amazonaws.com/dev
curl -H "Content-Type: application/json" https://xxxxxx.execute-api.eu-central-1.amazonaws.com/dev/api

# with enableApiKeyAuth=true
curl -H "x-api-key: {API-KEY}" -H "Content-Type: application/json" https://xxxxxx.execute-api.eu-central-1.amazonaws.com/dev/api/{route}


```

=> With the next request a new db.json file will be created in the S3 Bucket
Expand All @@ -153,13 +159,13 @@ curl -H "x-api-key: {API - KEY}" -H "Content-Type: application/json" https://xxx

[edit service property in serverless.yml (in root directory)](https://github.com/pharindoko/json-server-less-lambda/blob/66756961d960c44cf317ca307b097f595799a890/serverless.yml#L8)

#### Adapt settings in config/servleressconfig.yml file
#### Adapt settings in config/appconfig.yml file

| Attribute | Description | Type | Default |
|---|---|---|---|
| S3FILE | JSON file used as db to read and write (will be created with a default json value - customize in db.json) | string |db.json |
| S3BUCKET | S3-Bucket - this bucket must already exist in AWS | string | json-server-less-lambda-dev |
| READONLY | all API - write operations are forbidden (http 403)) | boolean | false |
| readOnly | Make API readonly - all API - write operations are forbidden (http 403)) | string |false |
| enableSwagger | Enable swagger and swagger UI support | string | true |
| enableApiKeyAuth | Make your routes private by using an additional ApiKey | boolean | false |

## Used Packages

Expand All @@ -170,7 +176,7 @@ curl -H "x-api-key: {API - KEY}" -H "Content-Type: application/json" https://xxx

## Components

- [NodeJS 8.10](https://nodejs.org/en/about/)
- [NodeJS 8.10](https://nodejs.org/en/about/)
- [AWS API Gateway](https://aws.amazon.com/api-gateway/)
- [AWS Lambda](https://aws.amazon.com/lambda/features/)
- [AWS S3](https://aws.amazon.com/s3/)
Expand All @@ -179,13 +185,14 @@ curl -H "x-api-key: {API - KEY}" -H "Content-Type: application/json" https://xxx

db.json file will be loaded directly from your local filesystem. No AWS access is needed.

#### Start solution
### Start solution

```bash
npm run start
```

#### Debug solution
### Debug solution

If you want to debug locally in VS Code everything is already setup (using webpack with sourcemap support)

```bash
Expand All @@ -194,13 +201,24 @@ npm run debug

#### 2. Test your API

To test you can use e.g. [Postman](https://www.getpostman.com/)
#### With Swagger

- Open Postman
- Enter as Url the endpoints url
Open the {ENDPOINTURL}: http://localhost:3000/ that you received as output

#### With Curl

1. replace the url with the url provided by serverless (see above)
2. replace the {API - KEY} with the key you get from serverless (see above)
3. replace {route} at the end of the url e.g. with posts (default value)

Default Schema:

```bash
https://localhost:3000/{route} #e.g. default value: https://localhost:3000/posts/
Default route is posts: (see db.json)
curl -H "Content-Type: application/json" http://localhost:3000/api/posts

#or another route given in db.json file
curl -H "Content-Type: application/json" http://localhost:3000/api/{route}
```

What`s my {route} ? -> see [json-server documentation](https://github.com/typicode/json-server)
Expand All @@ -209,7 +227,7 @@ What`s my {route} ? -> see [json-server documentation](https://github.com/typico

Use same componentes (S3, LowDB) as the lambda does but have code executed locally.

#### 1. Add .env file to root folder
### 1. Add .env file to root folder

**Mind:** If you haven`t deployed the solution yet, please create a private S3-Bucket and .json - file manually or deploy the solution first to AWS via serverless framework<br>
**Mind:** This function requires that you have access to AWS (e.g. via credentials)
Expand All @@ -224,9 +242,9 @@ cp .env.sample .env

| Attribute | Description | Type | Default |
|---|---|---|---|
| S3FILE | JSON file used as db to read and write (will be created with a default json value - customize in db.json) | string |db.json |
| S3BUCKET | S3-Bucket - this bucket must already exist in AWS | string | json-server-less-lambda-dev |
| READONLY | all API - write operations are forbidden (http 403)) | boolean | false |
| S3File | JSON file used as db to read and write (will be created with a default json value - customize in db.json) | string |db.json |
| S3Bucket | S3-Bucket - this bucket must already exist in AWS | string | json-server-less-lambda-dev |
| readOnly | all API - write operations are forbidden (http 403)) | boolean | false |

#### 2. Start solution

Expand All @@ -236,13 +254,28 @@ npm run dev

#### 3. Test your API

To test you can use e.g. [Postman](https://www.getpostman.com/)
#### With Swagger

Open the {ENDPOINTURL}: http://localhost:3000/ that you received as output

#### With Curl

1. replace the url with the url provided by serverless (see above)
2. replace the {API - KEY} with the key you get from serverless (see above)
3. replace {route} at the end of the url e.g. with posts (default value)

- Open Postman
- Enter as Url the endpoints url
Default Schema:

```bash
https://localhost:3000/{route} #e.g. default value: https://localhost:3000/posts
Default route is posts: (see db.json)
curl -H "Content-Type: application/json" http://localhost:3000/api/posts

# or another route given in db.json file
curl -H "Content-Type: application/json" http://localhost:3000/api/{route}

# with enableApiKeyAuth=true
curl -H "x-api-key: {API-KEY}" -H "Content-Type: application/json" https://xxxxxx.execute-api.eu-central-1.amazonaws.com/dev/api/{route}

```

What`s my {route} ? -> see [json-server documentation](https://github.com/typicode/json-server)
Expand All @@ -254,7 +287,7 @@ serverless-offline will help you to troubleshoot issues with the lambda executio
**Mind:** The assumption is that the solution has been already deployed<br>
**Mind:** This function requires that you have access to AWS (e.g. via credentials)

#### 1. build sources and execute serverless offline
### 1. build sources and execute serverless offline

- sources will be build with babel in advance to test the functionality.
- after that sls offline will be started
Expand All @@ -276,5 +309,39 @@ Serverless: Remember to use <b>x-api-key</b> on the request headers
- Replace {route} with the route you want to test e.g. /posts

<pre><code>
curl -H "x-api-key: {API-KEY}" -H "Content-Type: application/json" http://localhost:3000/{route}
</pre></code>
curl -H "x-api-key: {API-KEY}" -H "Content-Type: application/json" http://localhost:3000/api/{route}
</pre></code>

## FAQ

### How can I change the lambda region or stack name

Please have a look to the serverless guideline: https://serverless.com/framework/docs/providers/aws/guide/deploying/

### Cannot use Swagger UI when enableApiKeyAuth is true

The apiKey is set in AWS API Gateway. This means all requests (even the standard route) need to use the API-KEY.

If you want to see the Swagger UI you need to add a plugin e.g. ModHeader to Chrome and add the needed headers:
- Content-Type: application/json
- x-api-key: {provided by sls info in the output after deployment}

![ModHeader](docs/header.png)

### I forgot the API-KEY I have set

Ensure you have credentials for AWS set.

```bash
sls info
```

### Destroy the stack in the cloud

```bash
sls remove
```

### I deployed the solution but I get back a http 500 error

Check Cloudwatch Logs in AWS - the issue should be describe there. Log has the same name as the stack that has been created.
6 changes: 6 additions & 0 deletions config/appconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"readOnly": false,
"enableSwagger": true,
"enableApiKeyAuth": false
}

5 changes: 5 additions & 0 deletions config/serverlessconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"S3File": "db.json",
"S3Bucket": "${self:service}-${self:provider.stage}",
"basePath": "/${self:provider.stage}"
}
3 changes: 0 additions & 3 deletions config/serverlessconfig.yml

This file was deleted.

Binary file added docs/header.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/json-serverless.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit c8c0242

Please sign in to comment.