Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add OpenAPI 3.1 webhook support #1135

Merged
merged 7 commits into from
Jan 18, 2024
Merged

Conversation

federicobond
Copy link
Contributor

Hi! This is an initial implementation of support for declarative OpenAPI 3.1 webhooks using a new OpenApiWebhook class. Let me know if this approach sounds good and what else (besides docs) would be missing for a production implementation.

The current implementation requires webhooks to be declared manually in the SPECTACULAR_SETTINGS configuration, I did not want to commit to a particular way of discovering webhooks at the moment.

References #665

@federicobond
Copy link
Contributor Author

Some things to consider, now that I look at this again:

  • We could make the WEBHOOKS setting accept an import path to the webhook list/dict, so that SPECTACULAR_SETTINGS remain JSON-serializable.
  • We could provide a extend_schema-like decorator for serializer declarations to provide webhook details. Perhaps then just provide a list of fully qualified import paths to the annotated serializers in the settings?

Copy link

codecov bot commented Dec 27, 2023

Codecov Report

Attention: 4 lines in your changes are missing coverage. Please review.

Comparison is base (d78a21c) 98.59% compared to head (dbddbc3) 98.58%.
Report is 13 commits behind head on master.

Files Patch % Lines
drf_spectacular/plumbing.py 88.88% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1135      +/-   ##
==========================================
- Coverage   98.59%   98.58%   -0.01%     
==========================================
  Files          71       72       +1     
  Lines        8669     8766      +97     
==========================================
+ Hits         8547     8642      +95     
- Misses        122      124       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@federicobond federicobond marked this pull request as ready for review January 6, 2024 14:23
@federicobond
Copy link
Contributor Author

Hi @tfranzel, I hope you had a great start to the year! When you have some time, would you mind looking at this changeset and letting me know what you think of it?

Is there anything I can do to help make it easier to review?

@tfranzel
Copy link
Owner

hi @federicobond,

sry for the delay. thanks, hope you had an equally good start. Excellent PR btw.

So generally I like the PR. At first I was unsure about adding OpenApiWebhook, but I think it is the right thing to do as the callback is slightly different and the naming distinction is even in the specification.

We could make the WEBHOOKS setting accept an import path to the webhook list/dict, so that SPECTACULAR_SETTINGS remain JSON-serializable.

yes I agree, but not because of the JSON-serialization. Importing too much stuff in settings.py quickly results in import loops and since you likely want to use serializer classes in the decorator you pretty much have a loop there. So import path to a different file is the way to go.

I will look at it in detail in the upcoming days though.

@federicobond
Copy link
Contributor Author

federicobond commented Jan 11, 2024

Makes sense. I just pushed a modification to show how it would look for webhooks to be defined in settings as a list of import paths for each individual event.

Copy link
Owner

@tfranzel tfranzel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some comments about rearranging/simplifying stuff. The core itself I really like.

drf_spectacular/openapi.py Outdated Show resolved Hide resolved
drf_spectacular/generators.py Outdated Show resolved Hide resolved
drf_spectacular/generators.py Outdated Show resolved Hide resolved
drf_spectacular/generators.py Outdated Show resolved Hide resolved
@dashdanw
Copy link

Just want to thank you both for continuing to develop features for this package. 🙏

@federicobond federicobond force-pushed the webhooks branch 3 times, most recently from a6e211e to 0a97683 Compare January 12, 2024 00:56
@federicobond
Copy link
Contributor Author

@tfranzel I think I have addressed all your comments. Added docs too.

@federicobond
Copy link
Contributor Author

I keep wondering if there is a declarative approach that can be built on top of this, where you decorate your serializer declarations and they get automatically registered as webhooks.

@federicobond
Copy link
Contributor Author

One thing missing is versioning support. We could add an optional api_version parameter to OpenApiWebhook and do some simple filtering in process_webhooks.

@tfranzel
Copy link
Owner

One thing missing is versioning support. We could add an optional api_version parameter to OpenApiWebhook and do some simple filtering in process_webhooks.

It is currently analogous to callbacks, which is fine for me. Nobody ever asked about version there, so let's worry about it when it comes up.

I removed the type (I asked for) again, because it was pesky due to django's lazy string. Not important enough to waste too much time there.

Regarding responses, I would say it makes sense like that. The mechanics come from the regular processing, where it is also "required". If you go through the trouble of speccing callbacks/webhooks, I suppose you want to do it properly. You can surely take a shortcut with request=None, responses=None to fix it, but imho I wouldn't opt to suppress the warning by default. I like it like that.

Anyways, thanks @federicobond for this excellent PR. much appreciated!

@tfranzel tfranzel merged commit d52c9f3 into tfranzel:master Jan 18, 2024
35 checks passed
@federicobond federicobond deleted the webhooks branch January 18, 2024 19:47
@federicobond
Copy link
Contributor Author

Thanks @tfranzel!

On the topic of versioning (correct me if I'm wrong) the difference is that callbacks inherit the version from the operation they belong to, but webhooks are defined globally so they cannot do that. This is a feature I will need eventually, so I may open a pull request so we can discuss it separately.

@tfranzel
Copy link
Owner

That is indeed correct, I have not thought about it that deeply.

We can certainly pick this up again if you want, but I think this was a nice round package with a good scope. Extending it will be easier to reason about in a separate PR.

@federicobond
Copy link
Contributor Author

Sure! This is a great start.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants