Azure Functions で FastAPI/ASGI のAPIを動かす

## 概要

- Flask/WSGI同様にFastAPI/ASGIでもAzureクラウド上では動かすことができる
- ただし、2021/08現在はローカル環境の`func start`コマンドでは実行できない


## Flask/WSGI の記事

https://qiita.com/hkato/items/263c09095aaf53d6fcf7

> 多分FastAPI/ASGIなどなら azure.functions.AsgiMiddlewareで良いはず。

### FastAPIに変えた時の例

```python
import azure.functions as func

from fastapi_app.app import app   # app = FastAPI()


def main(req: func.HttpRequest, context: func.Context) -> func.HttpResponse:
    # ASGI Application
    return func.AsgiMiddleware(app).handle(req, context)
```

```
.
├── fastapi_app           # FastAPI/ASGI App
│   ├── __init__.py
│   └── app.py
├── functions_wsgi        # Functions entry -> ASGI
│   ├── __init__.py
│   └── function.json
├── host.json
└── requirements.txt
```
## Azure Functions Core Tools が古い問題(2021/08現在) 

[Azure Functions Core Tools](https://github.com/Azure/azure-functions-core-tools)の、[v3.0.3568](https://github.com/Azure/azure-functions-core-tools/releases/tag/3.0.3568)や[v3.0.3477](https://github.com/Azure/homebrew-functions/pull/81)(brewは古いまま更新されてない) に同梱されている、[Azure Functions Python Library](https://github.com/Azure/azure-functions-python-library)がv1.7.0で、ASGIに対応した[v1.7.1](https://github.com/Azure/azure-functions-python-library/releases/tag/1.7.1)以降が適用されていないので、ローカル実行時の環境では`azure.functions.AsgiMiddleware`が見つからず実行できない。

```sh
$ func start
Found Python version 3.8.6 (python3).

Azure Functions Core Tools
Core Tools Version:       3.0.3477 Commit hash: 5fbb9a76fc00e4168f2cc90d6ff0afe5373afc6d  (64-bit)
Function Runtime Version: 3.0.15584.0
.
.
.
Functions:

	functions_asgi: [GET,POST] http://localhost:7071/{*route}
.
.
.
[2021-08-09T02:24:09.212Z] Executing 'Functions.functions_asgi' (Reason='This function was programmatically called via the host APIs.', Id=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX)
[2021-08-09T02:24:09.261Z] Python HTTP trigger function processed a request.
[2021-08-09T02:24:09.332Z] Executed 'Functions.functions_asgi' (Failed, Id=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX, Duration=139ms)
[2021-08-09T02:24:09.333Z] System.Private.CoreLib: Exception while executing function: Functions.functions_asgi. System.Private.CoreLib: Result: Failure
[2021-08-09T02:24:09.333Z] Exception: AttributeError: module 'azure.functions' has no attribute 'AsgiMiddleware'
[2021-08-09T02:24:09.333Z] Stack:   File "/usr/local/Cellar/azure-functions-core-tools@3/3.0.3477/workers/python/3.8/OSX/X64/azure_functions_worker/dispatcher.py", line 399, in _handle__invocation_request
[2021-08-09T02:24:09.333Z]     call_result = await self._loop.run_in_executor(
[2021-08-09T02:24:09.333Z]   File "/Users/username/.anyenv/envs/pyenv/versions/3.8.6/lib/python3.8/concurrent/futures/thread.py", line 57, in run
[2021-08-09T02:24:09.333Z]     result = self.fn(*self.args, **self.kwargs)
[2021-08-09T02:24:09.333Z]   File "/usr/local/Cellar/azure-functions-core-tools@3/3.0.3477/workers/python/3.8/OSX/X64/azure_functions_worker/dispatcher.py", line 603, in _run_sync_func
[2021-08-09T02:24:09.333Z]     return ExtensionManager.get_sync_invocation_wrapper(context,
[2021-08-09T02:24:09.333Z]   File "/usr/local/Cellar/azure-functions-core-tools@3/3.0.3477/workers/python/3.8/OSX/X64/azure_functions_worker/extension.py", line 215, in _raw_invocation_wrapper
[2021-08-09T02:24:09.333Z]     result = function(**args)
[2021-08-09T02:24:09.333Z]   File "/Users/usernamew/Workspaces/sample-azure-functions-asgi-fastapi/functions_asgi/__init__.py", line 12, in main
[2021-08-09T02:24:09.333Z]     return func.AsgiMiddleware(app).handle(req, context)
```

## 暫定対応方法

### Core Tools 上でのローカルデバッグを諦める

[Uvicorn](https://www.uvicorn.org/)でデバッグし、Core Toolsのアップデートを待つ。

### Core Tools 上の Python Library を最新にアップデートする

`pip install -t`でCore Toolsの`workers`ディレクトリのものを差し替える。下記はmacOSなので別なプラットフォームの場合は、`3.8/OSX/X64` の部分を読み替え。

```sh
$ pip install azure-functions -t /usr/local/Cellar/azure-functions-core-tools@3/3.0.3477/workers/python/3.8/OSX/X64 --upgrade 
Collecting azure-functions
  Using cached azure_functions-1.7.2-py3-none-any.whl (137 kB)
Installing collected packages: azure-functions
Successfully installed azure-functions-1.7.2
```