You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
ResourceCollection.make_path() incorrectly adds trailing slash to terminal endpoints #31
ResourceCollection.make_path(part) always adds a trailing slash, even for terminal endpoints that shouldn't have one. This causes 405 Method Not Allowed errors when the client makes requests to servers with strict_slashes=True.
Problem
In interface.py, the ResourceCollection.make_path() method:
defmake_path(self, part: str|None=None) ->str:
"""Create a full path for a resource collection. Resource collection paths always end in a /. """ifpart:
return (
f"/{self.root.make_path(self.path).strip(SLASH)}"f"/{part.strip(SLASH)}/"
)
else:
returnf"/{self.root.make_path(self.path).strip(SLASH)}/"
This unconditionally adds a trailing slash when part is provided. However, this is incorrect for terminal endpoints (like /authorization_code) that are actions, not resource collections.
It generates /sessions/campus/authorization_code/ (with trailing slash), but the Flask route is defined as POST /sessions/<provider>/authorization_code (without trailing slash).
With strict_slashes=True on the server (which is needed to avoid 308 redirects that strip headers), this results in:
405 Method Not Allowed: The method is not allowed for the requested URL.
Suggested Fix
Add an end_slash parameter to ResourceCollection.make_path(), similar to Resource.make_path():
defmake_path(self, part: str|None=None, end_slash: bool=True) ->str:
"""Create a full path for a resource collection. Args: part: Optional sub-resource or action path. end_slash: Whether to add a trailing slash (default: True for collections). Returns: Full path for the resource collection or sub-resource. """ifpart:
base=f"/{self.root.make_path(self.path).strip(SLASH)}/{part.strip(SLASH)}"returnf"{base}/"ifend_slashelsebaseelse:
returnf"/{self.root.make_path(self.path).strip(SLASH)}/"
Then update from_code() to use end_slash=False:
deffrom_code(self, code: str) ->campus.model.AuthSession:
"""Get a session using authorization code."""resp=self.client.post(
self.make_path("authorization_code", end_slash=False),
json={"code": code}
)
# ...
Alternative
If changing the API is too disruptive, consider adding a separate method like make_action_path() for terminal endpoints that don't need trailing slashes.
Activity
Merge pull request #33 from nyjc-computing/dev/sync-devcontainer