Skip to content

REST API built with Express.js exposing an Azure SQL Database via Azure App Service.

Notifications You must be signed in to change notification settings

dreadted/azure-movies-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

77 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Azure Movies API

REST API built with Express.js exposing an Azure SQL Database via Azure App Service.

Contents

Built with

Installation

  1. Clone the repo

    git clone https://github.com/dreadnallen/azure-movies-api.git
  2. Install NPM packages

    npm install
  3. Add environment variables to /.env

    DBUser={your-username}
    DBPassword={your-password}
    DBServer={your-servername.database.windows.net}
  4. Run in development mode

    npm run dev

Deploy to Azure App Services

  1. Install Azure Tools for Visual Studio Code

  2. Go to Azure Extension / App Service and click + sign to Create New Web App... Choose name and platform (Windows)

  3. Go to Azure Portal and click "App Services" to find your new App Service:

    • Click Deployment Center under Deployment, choose GitHub under Continous Deployment and click Authorize
    • Log in to your GitHub account and click Continue
    • Click App Service Build Service and click Continue
    • Choose organization (your GitHub profile name), Repository and master branch
    • Click Countinue and Finish. Automatic deployment is now activated.
    • Click Configuration under Settings and click New application setting to add environment variables DBUser, DBPassword and DBServer.

    Alternatives: Deploy using Azure CLI or Visual Studio Code

  4. Change your package.json setting to:

    ...
    "scripts": {
        "start":"node build/server.js",
        "postinstall": "tsc"
      }
    ...
  5. Make sure typescript and @types/... are all in your package.json dependencies (npm install ... --save)

  6. Install the kuduscript tool globally (source)

    npm install kuduscript -g
  7. After installing Kuduscript, open a CMD window on your application’s root and type the following command to generate files .deployment and deploy.cmd in your application root directory (mind the dot: .):

    kuduscript -y --node --sitePath .
    
  8. Look for these lines in deploy.cmd

    :: 3. Install npm packages
    IF EXIST "%DEPLOYMENT_TARGET%\package.json" (
      pushd "%DEPLOYMENT_TARGET%"
      call :ExecuteCmd !NPM_CMD! install --production
      IF !ERRORLEVEL! NEQ 0 goto error
      popd
    )

    and add the following directly after them: (source)

    :: 4. Compile TypeScript
    echo Transpiling TypeScript in %DEPLOYMENT_TARGET%...call :ExecuteCmd node %DEPLOYMENT_TARGET%\node_modules\typescript\bin\tsc -p "%DEPLOYMENT_TARGET%"
  9. Make the following changes to web.config in order to point Node to your outDir directory setting in tsconfig.json:

    ...
    <handlers>
      <add name="iisnode" path="build/server.js" verb="*" modules="iisnode"/>
    </handlers>
    ...
    <rule name="DynamicContent">
      <conditions>
        <add input="{{REQUEST_FILENAME}}" matchType="IsFile" negate="True"/>
      </conditions>
      <action type="Rewrite" url="build/server.js"/>
    </rule>
  10. Make the following change to web.config in order to make your Node app catch any http errors (404 and 500 e.g.): (source)

    ...
    <httpErrors existingResponse="PassThrough"/>
    ...

API Reference

Genres

List genres

GET /v1/genres
Example request
$ curl --location --request GET 'https://azure-movies-api.azurewebsites.net/api/v1/genres'
Example response
200 - OK
[
  {
    "id": 1,
    "name": "{name}",
    "created-at": "{timestamp}",
    "updated-at": "{timestamp}",
    "_links": [
      {
        "self": {
          "href": "https://azure-movies-api.azurewebsites.net/api/v1/genres/1"
        }
      }
    ]
  },
  {
    "id": 2,
    "name": "{name}",
    "created-at": "{timestamp}",
    "updated-at": "{timestamp}",
    "_links": [
      {
        "self": {
          "href": "https://azure-movies-api.azurewebsites.net/api/v1/genres/2"
        }
      }
    ]
  }
]

Retrieve genre

GET /v1/genres/{genre-id}
Example request
$ curl --location --request GET 'https://azure-movies-api.azurewebsites.net/api/v1/genres'/{genre-id}
Path parameters
property type
genre-id integer requried
Example response
200 - OK
{
  "id": 1,
  "name": "{name}",
  "created-at": "{timestamp}",
  "updated-at": "{timestamp}",
  "_links": [
    {
      "self": {
        "href": "https://azure-movies-api.azurewebsites.net/api/v1/genres/1"
      }
    }
  ]
}

Create genre

POST /v1/genres
Example request
$ curl --location --request POST 'https://azure-movies-api.azurewebsites.net/api/v1/genres' \
--data-raw '{
    "name": "{name}"
}'
Request body
{
  "name": "{name}"
}
Body parameters
property type
name string required
Example response
201 - Created
{
  "id": 1,
  "name": "{name}"
}

Update genre

PUT /v1/genres/{genre-id}
Example request
$ curl --location --request PUT 'https://azure-movies-api.azurewebsites.net/api/v1/genres/{genre-id}' \
--data-raw '{
    "name": "{name}"
}'
Path parameters
property type
genre-id integer required
Request body
{
  "name": "{name}"
}
Body parameters
property type
name string required
Example response
200 - OK
{
  "id": 1,
  "name": "{name}",
  "created-at": "{timestamp}",
  "updated-at": "{timestamp}"
}

Delete genre

DELETE /v1/genres/{genre-id}
Example request
$ curl --location --request DELETE 'https://azure-movies-api.azurewebsites.net/api/v1/genres/{genre-id}
Path parameters
property type
genre-id integer required
Example response
200 - OK
{
  "id": 1
}

Movies

List movies

GET /v1/movies?genreId={genre-id}
Example request
$ curl --location --request GET 'https://azure-movies-api.azurewebsites.net/api/v1/movies?genreId=5'
Query parameters
property type
genre-id integer optional
Example response
200 - OK
[
  {
    "id": 1,
    "name": "{name}",
    "description": "{description}",
    "image-url": "{image-url}",
    "production-year": 2020,
    "created-at": "{timestamp}",
    "updated-at": "{timestamp}",
    "movie-genre": [
      {
        "id": 5,
        "name": "{genre-name}",
        "_links": [
          {
            "self": {
              "href": "https://azure-movies-api.azurewebsites.net/api/v1/genres/5"
            }
          }
        ]
      },
      {
        "id": 6,
        "name": "{genre-name}",
        "_links": [
          {
            "self": {
              "href": "https://azure-movies-api.azurewebsites.net/api/v1/genres/6"
            }
          }
        ]
      }
    ],
    "_links": [
      {
        "self": {
          "href": "https://azure-movies-api.azurewebsites.net/api/v1/movies/1"
        }
      }
    ]
  },
  {
    "id": 2,
    "name": "{name}",
    "description": "{description}",
    "image-url": "{image-url}",
    "production-year": 2020,
    "created-at": "{timestamp}",
    "updated-at": "{timestamp}",
    "movie-genre": [
      {
        "id": 5,
        "name": "{genre-name}",
        "_links": [
          {
            "self": {
              "href": "https://azure-movies-api.azurewebsites.net/api/v1/genres/5"
            }
          }
        ]
      }
    ],
    "_links": [
      {
        "self": {
          "href": "https://azure-movies-api.azurewebsites.net/api/v1/movies/2"
        }
      }
    ]
  }
]

Retrieve movie

GET /v1/movies/{movie-id}
Example request
$ curl --location --request GET 'https://azure-movies-api.azurewebsites.net/api/v1/movies/76'
Path parameters
property type
movie-id integer required
Example response
200 - OK
{
  "id": 1,
  "name": "{name}",
  "description": "{description}",
  "image-url": "{image-url}",
  "production-year": 2020,
  "created-at": "{timestamp}",
  "updated-at": "{timestamp}",
  "movie-genre": [
    {
      "id": 5,
      "name": "{genre-name}",
      "_links": [
        {
          "self": {
            "href": "https://azure-movies-api.azurewebsites.net/api/v1/genres/5"
          }
        }
      ]
    },
    {
      "id": 6,
      "name": "{genre-name}",
      "_links": [
        {
          "self": {
            "href": "https://azure-movies-api.azurewebsites.net/api/v1/genres/6"
          }
        }
      ]
    }
  ],
  "_links": [
    {
      "self": {
        "href": "https://azure-movies-api.azurewebsites.net/api/v1/movies/1"
      }
    }
  ]
}

Create movie

POST /v1/movies
Example request
$ curl --location --request POST 'https://azure-movies-api.azurewebsites.net/api/v1/movies/' \
--data-raw '{
    "name": "{name}",
    "description": "{description}",
    "production-year": 2020,
    "image-url": "http://example.com",
    "movie-genre": [
        {
            "id": 5
        },
        {
            "id": 6
        },
        {
            "id": 7
        }
    ]
}'
Request body
{
  "name": "{name}",
  "description": "{name}",
  "production-year": 2020,
  "image-url": "http://example.com",
  "movie-genre": [
    {
      "id": 5
    },
    {
      "id": 6
    },
    {
      "id": 7
    }
  ]
}
Body parameters
property type
name string required
description string required
production-year integer required
image-url string required
movie-genre (list of genre-ids) optional
Example response
201 - Created
{
  "id": 1,
  "name": "{name}",
  "description": "{description}",
  "image-url": "http://example.com",
  "production-year": 2020,
  "movie-genre": [
    {
      "id": 5,
      "name": "{name}"
    },
    {
      "id": 6,
      "name": "{name}"
    },
    {
      "id": 7,
      "name": "{name}"
    }
  ],
  "_links": [
    {
      "self": {
        "href": "https://azure-movies-api.azurewebsites.net/api/v1/movies/1"
      }
    }
  ]
}

Update movie

PUT /v1/movies/{movie-id}
Example request
$ curl --location --request PUT 'https://azure-movies-api.azurewebsites.net/api/v1/movies/1' \
--data-raw '{
	"id":463,
    "name": "{name}",
    "description": "{description}",
    "production-year": 2020,
    "image-url": "http://example.com",
    "movie-genre": [
        {
            "id": 7
        },
        {
            "id": 8
        }
    ]
}'
Request body
{
  "id": 463,
  "name": "{name}",
  "description": "{description}",
  "production-year": 2020,
  "image-url": "http://example.com",
  "movie-genre": [
    {
      "id": 7
    },
    {
      "id": 8
    }
  ]
}
Body parameters
property type
id integer required
name string required
description string required
production-year integer required
image-url string required
movie-genre (list of genre-ids) optional
Example response
200 - OK
{
  "id": 1,
  "name": "{name}",
  "description": "{description}",
  "image-url": "http://example.com",
  "production-year": 2020,
  "created-at": "{timestamp}",
  "updated-at": "{timestamp}",
  "movie-genre": [
    {
      "id": 7,
      "name": "{name}"
    },
    {
      "id": 8,
      "name": "{name}"
    }
  ],
  "_links": [
    {
      "self": {
        "href": "https://azure-movies-api.azurewebsites.net/api/v1/movies/1"
      }
    }
  ]
}

Delete movie

DELETE /v1/movies/{movie-id}
Example request
$ curl --location --request DELETE 'https://azure-movies-api.azurewebsites.net/api/v1/movies/1'
Path parameters
property type
movie-id integer required
Example response
200 - OK
{
  "id": 1
}

Actors

List actors

GET /v1/actors
Example request
$ curl --location --request GET 'https://azure-movies-api.azurewebsites.net/api/v1/actors'
Example response
200 - OK
[
  {
    "id": 6,
    "first-name": "{first-name}",
    "last-name": "{last-name}",
    "created-at": "{timestamp}",
    "updated-at": "{timestamp}",
    "_links": [
      {
        "self": {
          "href": "https://azure-movies-api.azurewebsites.net/api/v1/actors/6"
        }
      },
      {
        "roles": {
          "href": "https://azure-movies-api.azurewebsites.net/api/v1/actors/6/roles"
        }
      }
    ]
  },
  {
    "id": 7,
    "first-name": "{first-name}",
    "last-name": "{last-name}",
    "created-at": "{timestamp}",
    "updated-at": "{timestamp}",
    "_links": [
      {
        "self": {
          "href": "https://azure-movies-api.azurewebsites.net/api/v1/actors/7"
        }
      },
      {
        "roles": {
          "href": "https://azure-movies-api.azurewebsites.net/api/v1/actors/7/roles"
        }
      }
    ]
  }
]

Retrieve actor

GET /v1/actors/{actor-id}
Example request
$ curl --location --request GET 'https://azure-movies-api.azurewebsites.net/api/v1/actors/6'
Path parameters
property type
actor-id integer required
Example response
200 - OK
{
  "id": 6,
  "first-name": "{first-name}",
  "last-name": "{last-name}",
  "created-at": "{timestamp}",
  "updated-at": "{timestamp}",
  "_links": [
    {
      "self": {
        "href": "https://azure-movies-api.azurewebsites.net/api/v1/actors/6"
      }
    },
    {
      "roles": {
        "href": "https://azure-movies-api.azurewebsites.net/api/v1/actors/6/roles"
      }
    }
  ]
}

Create actor

POST /v1/actors
Example request
$ curl --location --request POST 'https://azure-movies-api.azurewebsites.net/api/v1/actors' \
--data-raw '{
    "first-name": "{first-name}",
    "last-name": "{last-name}"
}'
Request body
{
  "first-name": "{first-name}",
  "last-name": "{last-name}"
}
Body parameters
property type
first-name string required
last-name string optional
Example response
201 - Created
{
  "id": 1,
  "first-name": "{first-name}",
  "last-name": "{last-name}",
  "created-at": "{timestamp}",
  "_links": [
    {
      "self": {
        "href": "https://azure-movies-api.azurewebsites.net/api/v1/actors/1"
      }
    }
  ]
}

Update actor

PUT /v1/actors/{actor-id}
Example request
$ curl --location --request PUT 'https://azure-movies-api.azurewebsites.net/api/v1/actors/15' \
--data-raw '{
    "first-name": "{first-name}",
    "last-name": "{last-name}"
}'
Path parameters
property type
actor-id integer required
Request body
{
  "first-name": "{first-name}",
  "last-name": "{last-name}"
}
Body parameters
property type
first-name string required
last-name string optional
Example response
200 - OK
{
  "id": 15,
  "first-name": "{first-name}",
  "last-name": "{last-name}",
  "created-at": "{timestamp}",
  "updated-at": "{timestamp}",
  "_links": [
    {
      "self": {
        "href": "https://azure-movies-api.azurewebsites.net/api/v1/actors/15"
      }
    }
  ]
}

Delete actor

DELETE /v1/actors/{actor-id}
Example request
$ curl --location --request DELETE 'https://azure-movies-api.azurewebsites.net/api/v1/actors/15'
Path parameters
property type
actor-id integer required
Example response
200 - OK
{
  "id": 15
}

Roles

List actor roles

GET /v1/actors/{actor-id}/roles
Example request
curl --location --request GET 'https://azure-movies-api.azurewebsites.net/api/v1/actors/6/roles'
Path parameters
property type
actor-id integer required
Example response
200 - OK
[
  {
    "id": 10,
    "name": "{name}",
    "movie-id": 76,
    "actor-id": 6,
    "_links": [
      {
        "movie": {
          "href": "https://azure-movies-api.azurewebsites.net/api/v1/movies/76"
        }
      },
      {
        "actor": {
          "href": "https://azure-movies-api.azurewebsites.net/api/v1/actors/6"
        }
      }
    ]
  }
]

List actor roles for a particular movie

GET /v1/actors/{actor-id}/roles/{movie-id}
Example request
$ curl --location --request GET 'http://azure-movies-api.azurewebsites.net/api/v1/actors/6/roles/76'
Path parameters
property type
actor-id integer required
movie-id integer required
Example response
200 - OK
[
  {
    "id": 10,
    "name": "{name}",
    "movie-id": 76,
    "actor-id": 6,
    "_links": [
      {
        "movie": {
          "href": "https://azure-movies-api.azurewebsites.net/api/v1/movies/76"
        }
      },
      {
        "actor": {
          "href": "https://azure-movies-api.azurewebsites.net/api/v1/actors/6"
        }
      }
    ]
  }
]

Create role

POST /v1/actors/{actor-id}/roles/{movie-id}
Example request
$ curl --location --request POST 'https://azure-movies-api.azurewebsites.net/api/v1/actors/16/roles/77' \
--data-raw '{
    "name": "{name}"
}'
Path parameters
property type
actor-id integer required
movie-id integer required
Request body
{
  "name": "{name}"
}
Body parameters
property type
name string required
Example response
201 - Created
{
  "id": 26,
  "name": "{name}",
  "movie-id": 77,
  "actor-id": 16,
  "_links": [
    {
      "movie": {
        "href": "https://azure-movies-api.azurewebsites.net/api/v1/movies/77"
      }
    },
    {
      "actor": {
        "href": "https://azure-movies-api.azurewebsites.net/api/v1/actors/16"
      }
    }
  ]
}

Delete role

DELETE /v1/actors/{actor-id}/roles/{movie-id}/{role-id}
Example request
$ curl --location --request DELETE 'https://azure-movies-api.azurewebsites.net/api/v1/actors/16/roles/77/26'
Path parameters
property type
actor-id integer required
movie-id integer required
role-id integer required
Example response
200 - OK
{
  "movie-id": 77,
  "actor-id": 16,
  "_links": [
    {
      "movie": {
        "href": "https://azure-movies-api.azurewebsites.net/api/v1/movies/77"
      }
    },
    {
      "actor": {
        "href": "https://azure-movies-api.azurewebsites.net/api/v1/actors/16"
      }
    }
  ]
}

Contact

email: [email protected] linkedin: https://www.linkedin.com/in/laurin/

About

REST API built with Express.js exposing an Azure SQL Database via Azure App Service.

Resources

Stars

Watchers

Forks

Packages

No packages published