jamesh625
jamesh625

Reputation: 785

Azure Function being called by another in same project does not respond (freezes)

I have two Azure Functions in the same project in VS Code. They are written in Python 3.8. They are both HTTP-triggered with either a GET or POST request. They were made using the Azure Functions extension for VS Code.

Their authorization levels are both set to anonymous, meaning they should accept requests from anywhere.

They have identical HttpTrigger[1, 2]/function.json files:

{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    }
  ]
}

I am trying to use HttpTrigger1 to make a GET request to HttpTrigger2 using the requests library.

HttpTrigger1/__init__.py:

import logging
import requests
import azure.functions as func


def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info("Python HTTP trigger function processed a request.")
    requests.get("http://localhost:7071/api/HttpTrigger2")

    return func.HttpResponse(
        "HttpTrigger1 executed successfully.",
        status_code=200,
    )

HttpTrigger2/__init__.py:

import logging

import azure.functions as func


def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info("Python HTTP trigger function processed a request.")

    return func.HttpResponse(
        "HttpTrigger2 executed successfully.",
        status_code=200,
    )

The log file outputs:

> Executing task: .venv/bin/python -m pip install -r requirements.txt <

Requirement already satisfied: azure-functions in ./.venv/lib/python3.8/site-packages (from -r requirements.txt (line 5)) (1.6.0)
source /home/jim/azureTest/.venv/bin/activCollecting requests
ate
  Using cached requests-2.25.1-py2.py3-none-any.whl (61 kB)
Collecting idna<3,>=2.5
  Using cached idna-2.10-py2.py3-none-any.whl (58 kB)
Collecting chardet<5,>=3.0.2
  Using cached chardet-4.0.0-py2.py3-none-any.whl (178 kB)
Collecting urllib3<1.27,>=1.21.1
  Using cached urllib3-1.26.3-py2.py3-none-any.whl (137 kB)
Collecting certifi>=2017.4.17
  Using cached certifi-2020.12.5-py2.py3-none-any.whl (147 kB)
Installing collected packages: idna, chardet, urllib3, certifi, requests
Successfully installed certifi-2020.12.5 chardet-4.0.0 idna-2.10 requests-2.25.1 urllib3-1.26.3

Terminal will be reused by tasks, press any key to close it.

> Executing task: . .venv/bin/activate && func host start <

Found Python version 3.8.5 (python3).

Azure Functions Core Tools
Core Tools Version:       3.0.3388 Commit hash: fb42a4e0b7fdc85fbd0bcfc8d743ff7d509122ae 
Function Runtime Version: 3.0.15371.0


Functions:

        HttpTrigger1: [GET,POST] http://localhost:7071/api/HttpTrigger1

        HttpTrigger2: [GET,POST] http://localhost:7071/api/HttpTrigger2

For detailed output, run func with --verbose flag.
[2021-03-15T06:15:36.426Z] Worker process started and initialized.
[2021-03-15T06:15:40.953Z] Host lock lease acquired by instance ID '000000000000000000000000861DE9B7'.
[2021-03-15T06:15:45.946Z] Executing 'Functions.HttpTrigger1' (Reason='This function was programmatically called via the host APIs.', Id=a82a749d-4e0d-40e4-b9ff-358c8e38a24e)
[2021-03-15T06:15:46.039Z] Python HTTP trigger function processed a request.
[2021-03-15T06:15:46.046Z] Executing 'Functions.HttpTrigger2' (Reason='This function was programmatically called via the host APIs.', Id=c3291b34-ee0d-4b5d-8b67-1a1bcb4474f6)

However, execution never advances. HttpTrigger2 never logs anything, nor does control return to HttpTrigger1. How should I make a HTTP request from one Azure Function to another? The log doesn't show any errors, and calling HttpTrigger2 without going through HttpTrigger1 works as expected. Behaviour is the same whether I go to the browser and type http://localhost:7071/api/HttpTrigger1, make a request with Postman or use the Azure Functions extension to "Execute Function Now".

Upvotes: 2

Views: 1004

Answers (3)

jamesh625
jamesh625

Reputation: 785

I've accepted a different response as the best answer, but thought I would also post my own solution using http3 here for completeness.

HttpTrigger1/__init__.py:

import logging
import http3
import azure.functions as func


async def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info("Python HTTP trigger function processed a request.")
    client = http3.AsyncClient()
    await client.get("http://localhost:7071/api/HttpTrigger2")

    return func.HttpResponse(
        "HttpTrigger1 executed successfully.",
        status_code=200,
    )

HttpTrigger2/__init__.py:

import logging

import azure.functions as func


def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info("Python HTTP trigger function processed a request.")

    return func.HttpResponse(
        "HttpTrigger2 executed successfully.",
        status_code=200,
    )

Upvotes: 1

Kashyap
Kashyap

Reputation: 17441

One host instance would serve one Function at a time. As Bowman said if you use async then you can work around that problem.

If for some reason you don't want to use async then other options:

  • (not tested) use multiple worker processes in a host. Not sure if this is supported in local environment or not. Beware that this will cause each process to share that host's resources.
  • deploy to cloud and test. It should scale the worker processes and spawn a new instance to host second function.

Upvotes: 1

suziki
suziki

Reputation: 14088

import logging

import azure.functions as func
import requests_async as requests

async def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')
    response = await requests.get('http://localhost:7071/api/HttpTrigger2')
    return func.HttpResponse(
            "Test"+response.text,
            status_code=200
    )

https://pypi.org/project/requests-async/

Upvotes: 2

Related Questions