Marlon Costa
Marlon Costa

Reputation: 107

How do I call another path on FastAPI?

I'm working on an API that returns some files from a local folder, to simulate a system that we have for the developer environment.

Most of the system works by putting the code that identifies the person and returning his file. but, one path of this system has a unique behavior: It uses a POST method (with the request body containing the Id code), and I'm struggling to make it work.

This is my current code:

import json
from pathlib import Path

import yaml
from fastapi import FastAPI
from pydantic.main import BaseModel


app = FastAPI()

class RequestModel(BaseModel):
    assetId: str


@app.get("/{group}/{service}/{assetId}")
async def return_json(group: str, service: str, assetId: str):
    with open("application-dev.yml", "r") as config_file:
        output_dir = yaml.load(config_file)['path']
        path = Path(output_dir + f"{group}/{service}/")

    file = [f for f in path.iterdir() if f.stem == assetId][0]

    if file.exists():
        with file.open() as target_file:
            return json.load(target_file)


@app.post("/DataService/ServiceProtocol")
async def return_post_path(request: RequestModel):
    return return_json("DataService", "ServiceProtocol", request.msisdn)

I had the idea to call another path/function from the API itself to return the desired value, but I'm getting this error:

ValueError: [TypeError("'coroutine' object is not iterable"), TypeError('vars() argument must have __dict__ attribute')]

Upvotes: 6

Views: 11400

Answers (1)

Hans Musgrave
Hans Musgrave

Reputation: 7141

Your return_json function returns a coroutine (note the async keyword in its definition). Note that @app.post(...) is expecting a coroutine which returns data, not a coroutine which returns another coroutine. The most straightforward changes are:

@app.post("/DataService/ServiceProtocol")
async def return_post_path(request: RequestModel):
    # unpack return_json into a non-coroutine object before returning it
    return await return_json("DataService", "ServiceProtocol", request.msisdn)
@app.post("/DataService/ServiceProtocol")
def return_post_path(request: RequestModel):
    # return the coroutine directly because we're inside a normal function
    return return_json("DataService", "ServiceProtocol", request.msisdn)

Upvotes: 6

Related Questions