Sunny Tambi
Sunny Tambi

Reputation: 2483

403 (Forbidden) while calling one azure function from another

I need to call an azure function; fn(b), from another azure function; fn(a).

fn(a) -> fn(b)

Both these functions are in same function app. The problem is whenever I try to call (b), I get 403-Forbidden "data at the root level is invalid".

Is it possible to call an azure function from another azure function within same function app?

Function 1

public static class Function1
    {
        [FunctionName("Function1")]
        public static async Task<HttpResponseMessage> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)]
            HttpRequestMessage req, TraceWriter log)
        {
            log.Info("---- C# HTTP trigger function 1 processed a request.");

            UploadToF2(log);
            return null;
        }

        private static IRestResponse UploadToF2(TraceWriter log)
        {
            SomeObject payload = new SomeObject();
            payload.One = "One";
            payload.Two = 2;
            payload.Three = false;
            payload.Four = 4.4;

            var Fn2Url = Convert.ToString(ConfigurationManager.AppSettings["F2Url"]);
            log.Info("Hitting F2 at " + Fn2Url);
            var method = Method.POST;
            var client = new RestClient(Fn2Url);
            var body = JsonConvert.SerializeObject(payload);

            var request = new RestRequest(method);
            request.RequestFormat = DataFormat.Json;
            request.AddHeader("Content-Type", "application/json");

            request.AddBody(payload); // uses JsonSerializer

            IRestResponse response = client.Execute(request);
            return response;
        }
    }

    class SomeObject
    {
        public string One { get; set; }
        public int Two { get; set; }
        public bool Three { get; set; }
        public double Four { get; set; }
    }

Function 2

public static class Function2
    {
        [FunctionName("Function2")]
        public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log)
        {
            log.Info("---- C# HTTP trigger function 2 processed a request.");
            string payload = await req.Content.ReadAsStringAsync();
            log.Info("payload == "+payload);

            return null;
        }
    }

Additional Information:

  1. F2Url is a fully qualified url coming from config.
  2. I tried running both functions in localhost. It works. I.e. fn(a) can call fn(b) in localhost. However when I host both of them in Azure, fn(b) is not callable from fn(a).
  3. I tried a hybrid test too. I.e. I kept one function in local and another one in Azure. It works this way too. I.e. I kept fn(a) in local and fn(b) in Azure, fn(b) is callable.
  4. I tried calling fn(b) directly from Postman and again it works.
  5. authLevel is anonymous for both functions
  6. I have IP restrictions (Platform features > Networking > IP restrictions) applied to the Function app. When I remove IP restrictions, Function1 is able to call Function2. However keeping IP restrictions, the call is not allowed.

The only condition when fn(a) cannot call fn(b) is when both these functions are hosted in Azure.

Upvotes: 1

Views: 15738

Answers (3)

Tom Sun
Tom Sun

Reputation: 24549

403 (Forbidden) while calling one azure function from another

If don't add the client Ip in the IP restrictions, then you test it in you client will get 403 error. Not only call on azure function from another ,but also all functions are restricted if you don't add the client IP in the IP restrictions.

In your case, you need to add your test client Ip in the IP restrictions, then it will work.

enter image description here

enter image description here

Update:

Add the test result.

enter image description here

Upvotes: 2

evilSnobu
evilSnobu

Reputation: 26324

  1. Call Function #2 by its full URL, since there's a front end layer that gets hit first before the request makes it to your function app. This is true even for functions calling each other within the same function app.

    GET https://{func-app-name}.azurewebsites.net/api/function2
    
  2. If the authLevel is not anonymous in function.json, pass in the API key as ?code=

    https://{func-app-name}.azurewebsites.net/api/function2?code={API-key}
    

    or as a header —

    GET https://{func-app-name}.azurewebsites.net/api/function2
    x-functions-key: {API-key}
    

When running locally (Visual Studio/func host start), the value of authLevel is ignored. Looking at your decorator, AuthorizationLevel.Anonymous is present so most probably that's not it.

More on authorization keys here.

On top of that, you could do better that returning null in Function #2: 200 OK, 202 Accepted, 204 No Content, all valid choices depending on what's supposed to happen next (async/sync processing).

Upvotes: 0

Horia Toma
Horia Toma

Reputation: 1129

Works locally through a GET to Function1 when using:

var Fn2Url = "http://localhost:7071/api/Function2";

What value are you using in your configuration?

Upvotes: 0

Related Questions