Migrate ratings endpoints from web.py to FastAPI#12001
Migrate ratings endpoints from web.py to FastAPI#12001RayBB merged 25 commits intointernetarchive:masterfrom
Conversation
for more information, see https://pre-commit.ci
for more information, see https://pre-commit.ci
RayBB
left a comment
There was a problem hiding this comment.
Few minor comments, but it's a good start. Please request another review when you push up the fixes.
|
Also removed JSONResponse wrapping from (GET) rating endpoint. |
RayBB
left a comment
There was a problem hiding this comment.
Two small things here, but it looks really good. I'm excited to test it soon.
RayBB
left a comment
There was a problem hiding this comment.
A few small changes and then I'll look again!
RayBB
left a comment
There was a problem hiding this comment.
I pushed up some very minor changes.
However, this PR isn't complete. It does not handle most of the options possible for the post request.
Make sure the functionality is compatible with the old endpoint. ajax, redir, redir_url, and page need to be implemented.
Before asking me to review this again please be sure to test all of this functionality yourself to ensure it has pretty much the same response as the old endpoint.
|
@395ShikharSingh do you plan to keep working on this or can it be assigned to someone else? |
2003c77 to
0c8383c
Compare
|
Hey @RayBB sorry for the delay! I've added full legacy compatibility to the POST endpoint (redir, redir_url, page, ajax, edition_id) and added unit tests covering all scenarios. Tested locally and everything is working. Let me know if anything needs. |
RayBB
left a comment
There was a problem hiding this comment.
Thanks for the quick followup. I know mine have been slow lately.f
We're in the right direction and there's still quite a bit more feedback to address here. When in doubt please follow the way that other fastapi endpoints look.
|
|
||
|
|
||
| @pytest.fixture | ||
| def fastapi_client(monkeypatch): |
There was a problem hiding this comment.
This already exists. Please do not recreate it.
|
|
||
|
|
||
| @pytest.fixture | ||
| def authenticated_client(fastapi_client): |
There was a problem hiding this comment.
We now have mock_authenticated_user that you can use instead as long as your PR is caught up with master
| return redir_url or edition_id or f"/works/OL{work_id}W" | ||
|
|
||
|
|
||
| def _get_absolute_redirect_url(request: Request, path: str) -> str: |
There was a problem hiding this comment.
Please don't add one line function definitions unless there is a very good reason.
Please keep all of this as similar as possible to the old endpoint instead restructuring it when not needed.
| @router.post("/works/OL{work_id}W/ratings", tags=["internal"], include_in_schema=SHOW_INTERNAL_IN_SCHEMA, response_model=None) | ||
| @router.post("/works/OL{work_id}W/ratings.json", tags=["internal"], include_in_schema=SHOW_INTERNAL_IN_SCHEMA, response_model=None) | ||
| async def post_ratings( | ||
| request: Request, |
There was a problem hiding this comment.
We should only use a raw request in special cases. In this case, inline the values just like we do with the others in this file on master. This gives us clearer documentation and follows best practices from fastapi.
| if not user: | ||
| return RedirectResponse(_get_absolute_redirect_url(request, f"/account/login?redirect={key}"), status_code=303) |
There was a problem hiding this comment.
We don't need to do this. It's an authenticated endpoint.
| async def post_ratings( | ||
| request: Request, | ||
| work_id: Annotated[int, Path()], | ||
| user: Annotated[AuthenticatedUser | None, Depends(get_authenticated_user)], |
There was a problem hiding this comment.
use require_authenticated_user because they must be logged in to use this.
| else: | ||
| try: | ||
| rating = int(data["rating"]) | ||
| if rating not in models.Ratings.VALID_STAR_RATINGS: |
There was a problem hiding this comment.
We won't need this because we should validate using the gt and lt options in the endpoint params
| except (TypeError, ValueError): | ||
| return {"error": "invalid rating"} |
| if data.get("redir") and not data.get("ajax"): | ||
| return _build_rating_redirect_response(request, key, data.get("page")) |
There was a problem hiding this comment.
Don't make a new function here. Keep it inline and simple.
|
One quick clarification before I push the next revision: for /works/OL{work_id}W/ratings, should legacy compatibility take priority over the usual FastAPI pattern when they conflict?
Since your earlier feedback was to keep this compatible with the old endpoint, I wanted to confirm whether for this endpoint I should preserve the legacy behavior exactly in those cases. |
|
These can differ (follow modern fastapi):
This is a good question. In this case please ensure we have the exact same functionality. If before it was only query params then now it should accept query params. If it has working with forms before it should work with forms now:
|
|
Addressed the remaining /ratings migration feedback. |
RayBB
left a comment
There was a problem hiding this comment.
@395ShikharSingh really excellent work here.
Since this is an internal endpoint I ultimately ended up deciding that instead of making the code so complicated supporting query params and redirects that we could just drop those. We already were not using the query params and the redirects only triggered when there is no JS (and for little gain at that). Since we're now in an OL world where we expect JS it's ok to remove that.
Anyway, your work is appreciated and you can look at the last couple commits I added to learn more. Let me know if you have questions!
referring: #11999
Changes
openlibrary/fastapi/internal/api.pyget_ratingsGET and POST as standalone decorated functionsopenlibrary/plugins/openlibrary/api.pyscripts/test_ratings_migration.shDifferences
/account/login(303){"error": "invalid rating"}Stakeholder
@RayBB