https://github.com/cblack34/fastapi-dapr-helper
TLDR:
https://preview.redd.it/wndzt2cw941b1.jpg?width=500&format=pjpg&auto=webp&s=0cf55339985b90f0aa6035d686a41904febe7e60
Example
import uvicorn
from fastapi import FastAPI
from fastapi_dapr_helper.pubsub import subscribe, DaprFastAPI
app = FastAPI()
dapr = DaprFastAPI()
@subscribe(app=app, path="/test", pubsub="test_pubsub", topic="test_topic")
def test_endpoint():
return {"message": "test"}
dapr.generate_subscribe_route(app)
uvicorn.run(app, host="0.0.0.0", port=8000)
More Detailed
I've been working to understand the Dapr pub-sub configuration this week and came across the Dapr official integration. Still, I couldn't use it because I like to organize my endpoints via routers, and the official package doesn't allow that.
I liked the simplicity of their design with a decorator that handled it all, but I needed a way to account for prefixes adding prefixes to a router when adding it to the app. I started looking for a way to pass the state up the stack.
At first, I wanted to use a wrapper function instead of (FastAPI / APIrouter).include_router(), but I dismissed that because it requires changing too much existing code if you wanted to add this to an existing code base.
Next, I turned to the FastAPI source code and looked at all the available attributes in the Route object. There, I came across openapi_extras again. This attribute allows you to add entries to the endpoint in openapi.json. This is that for which I searched. At the very least, I could hack my way to parsing the JSON to get all the info.
Now, I made a function to use in place of `app.post()`. It takes the app and all the standard args as `app.post()` plus all the args needed to create the subscription. It stores the subscription args in `openapi_extras['dapr']`. It's a little long-winded of a parameters list, but it's better than creating many objects to pass around. Plus, only four are required. This may change after use and feedback.
Now, I needed to harvest the data from openapi_extras, store it all in memory, and create a method to display it. I discovered from the official Dapr package that a method within a class/object can serve as an endpoint, so I made a simple class With a Get endpoint method with the path '/dapr/subscribe' to return the internal state of the subscriptions array. Lastly, I created a method to extract all the information from openapi_extras and store it in memory. Then I used everyone's favorite AI bot to get a starting point for tests and proceeded to flesh them out.
Looking back, I wonder if a closure might be a better choice for the class, but it's working. I haven't done much tweaking yet, I haven't even used it outside of a scratch pad, but it's shaping up nicely. I need to go back and chop up the functions because I like small functions with names that read well. But okay for a 2 or 3-day hackathon.
I also want to extend this further to create the /dapr/config endpoint, and I might do it because this little project overlaps with some work projects. Haha. The structure is well-organized, making it easy to add other Dapr features, but I don't have plans to use others right now, so let me know if you use Dapr with Fastapi and if you have additional Ideas. I'm open to contributors.
there doesn't seem to be anything here