Skip to content

Migrate ratings endpoints from web.py to FastAPI#12001

Merged
RayBB merged 25 commits intointernetarchive:masterfrom
Shikhar-395:feature/migrate-ratings-to-fastapi
Mar 27, 2026
Merged

Migrate ratings endpoints from web.py to FastAPI#12001
RayBB merged 25 commits intointernetarchive:masterfrom
Shikhar-395:feature/migrate-ratings-to-fastapi

Conversation

@Shikhar-395
Copy link
Copy Markdown
Contributor

referring: #11999

Changes

openlibrary/fastapi/internal/api.py

  • Added get_ratings GET and POST as standalone decorated functions

openlibrary/plugins/openlibrary/api.py

scripts/test_ratings_migration.sh

Differences

Aspect Legacy (web.py) FastAPI
GET response JSON identical identical
POST response JSON identical identical
Authentication Redirects to /account/login (303) Returns 401 Unauthorized
Invalid rating 200 + {"error": "invalid rating"} 422 Unprocessable Entity

Stakeholder

@RayBB

Copy link
Copy Markdown
Collaborator

@RayBB RayBB left a comment

Choose a reason for hiding this comment

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

Few minor comments, but it's a good start. Please request another review when you push up the fixes.

Comment thread openlibrary/fastapi/internal/api.py Outdated
Comment thread openlibrary/fastapi/internal/api.py Outdated
Comment thread openlibrary/fastapi/internal/api.py Outdated
Comment thread openlibrary/fastapi/internal/api.py Outdated
Comment thread openlibrary/fastapi/internal/api.py Outdated
Comment thread openlibrary/fastapi/internal/api.py Outdated
@Shikhar-395
Copy link
Copy Markdown
Contributor Author

Also removed JSONResponse wrapping from (GET) rating endpoint.

@Shikhar-395 Shikhar-395 requested a review from RayBB March 4, 2026 22:17
Copy link
Copy Markdown
Collaborator

@RayBB RayBB left a comment

Choose a reason for hiding this comment

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

Two small things here, but it looks really good. I'm excited to test it soon.

Comment thread openlibrary/fastapi/internal/api.py Outdated
Comment thread openlibrary/fastapi/internal/api.py Outdated
@Shikhar-395 Shikhar-395 requested a review from RayBB March 5, 2026 02:16
@RayBB RayBB self-assigned this Mar 5, 2026
@github-project-automation github-project-automation Bot moved this to Waiting Review/Merge from Staff in Ray's Project Mar 5, 2026
Copy link
Copy Markdown
Collaborator

@RayBB RayBB left a comment

Choose a reason for hiding this comment

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

A few small changes and then I'll look again!

Comment thread openlibrary/fastapi/internal/api.py Outdated
Comment thread openlibrary/fastapi/internal/api.py Outdated
Comment thread openlibrary/fastapi/internal/api.py Outdated
Copy link
Copy Markdown
Collaborator

@RayBB RayBB left a comment

Choose a reason for hiding this comment

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

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.

@RayBB RayBB removed the On Testing label Mar 15, 2026
@Shikhar-395 Shikhar-395 marked this pull request as draft March 17, 2026 15:53
@RayBB
Copy link
Copy Markdown
Collaborator

RayBB commented Mar 23, 2026

@395ShikharSingh do you plan to keep working on this or can it be assigned to someone else?

@Shikhar-395 Shikhar-395 force-pushed the feature/migrate-ratings-to-fastapi branch from 2003c77 to 0c8383c Compare March 24, 2026 00:07
@Shikhar-395 Shikhar-395 marked this pull request as ready for review March 24, 2026 00:44
@Shikhar-395
Copy link
Copy Markdown
Contributor Author

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.

Copy link
Copy Markdown
Collaborator

@RayBB RayBB left a comment

Choose a reason for hiding this comment

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

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):
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This already exists. Please do not recreate it.



@pytest.fixture
def authenticated_client(fastapi_client):
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We now have mock_authenticated_user that you can use instead as long as your PR is caught up with master

Comment thread openlibrary/fastapi/internal/api.py Outdated
return redir_url or edition_id or f"/works/OL{work_id}W"


def _get_absolute_redirect_url(request: Request, path: str) -> str:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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.

Comment thread openlibrary/fastapi/internal/api.py Outdated
@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,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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.

Comment thread openlibrary/fastapi/internal/api.py Outdated
Comment on lines +129 to +130
if not user:
return RedirectResponse(_get_absolute_redirect_url(request, f"/account/login?redirect={key}"), status_code=303)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We don't need to do this. It's an authenticated endpoint.

Comment thread openlibrary/fastapi/internal/api.py Outdated
async def post_ratings(
request: Request,
work_id: Annotated[int, Path()],
user: Annotated[AuthenticatedUser | None, Depends(get_authenticated_user)],
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

use require_authenticated_user because they must be logged in to use this.

Comment thread openlibrary/fastapi/internal/api.py Outdated
else:
try:
rating = int(data["rating"])
if rating not in models.Ratings.VALID_STAR_RATINGS:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We won't need this because we should validate using the gt and lt options in the endpoint params

Comment thread openlibrary/fastapi/internal/api.py Outdated
Comment on lines +142 to +143
except (TypeError, ValueError):
return {"error": "invalid rating"}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

we also will not need this

Comment thread openlibrary/fastapi/internal/api.py Outdated
Comment on lines +153 to +154
if data.get("redir") and not data.get("ajax"):
return _build_rating_redirect_response(request, key, data.get("page"))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Don't make a new function here. Keep it inline and simple.

@github-actions github-actions Bot added the Needs: Response Issues which require feedback from lead label Mar 24, 2026
@Shikhar-395
Copy link
Copy Markdown
Contributor Author

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?
I’m asking because there are a few remaining cases where the old endpoint and the standard FastAPI approach differ:

  • unauthenticated POST: legacy redirects to login, while require_authenticated_user returns 401
  • invalid rating: legacy returns {"error": "invalid rating"} with 200, while param validation returns 422
  • legacy web.input() accepts POST query params like ajax, redir, redir_url, and page, while plain Form(...) handling does not

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.

@RayBB
Copy link
Copy Markdown
Collaborator

RayBB commented Mar 24, 2026

These can differ (follow modern fastapi):

  • unauthenticated POST: legacy redirects to login, while require_authenticated_user returns 401
  • invalid rating: legacy returns {"error": "invalid rating"} with 200, while param validation returns 422

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:

  • legacy web.input() accepts POST query params like ajax, redir, redir_url, and page, while plain Form(...) handling does not

@RayBB RayBB added Needs: Submitter Input Waiting on input from the creator of the issue/pr [managed] and removed Needs: Response Issues which require feedback from lead labels Mar 24, 2026
@github-actions github-actions Bot removed the Needs: Submitter Input Waiting on input from the creator of the issue/pr [managed] label Mar 25, 2026
@Shikhar-395
Copy link
Copy Markdown
Contributor Author

Addressed the remaining /ratings migration feedback.
POST now accepts the legacy inputs via both form data and query params (ajax, redir, redir_url, page, rating, edition_id) while keeping the modern FastAPI behavior we discussed for auth (401) and invalid rating validation (422).
I also switched the ratings tests to the shared FastAPI fixtures, and updated the shared FastAPI test client setup in conftest.py so these endpoint tests can use that common fixture cleanly.

@github-actions github-actions Bot added the Needs: Response Issues which require feedback from lead label Mar 25, 2026
Copy link
Copy Markdown
Collaborator

@RayBB RayBB left a comment

Choose a reason for hiding this comment

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

@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!

@RayBB RayBB merged commit 17a45a5 into internetarchive:master Mar 27, 2026
4 checks passed
@github-project-automation github-project-automation Bot moved this from Waiting Review/Merge from Staff to Done in Ray's Project Mar 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Needs: Response Issues which require feedback from lead

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants