-
Notifications
You must be signed in to change notification settings - Fork 2.2k
fix: resolve URL path truncation in SSE transport for proxied servers #1211
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
base: main
Are you sure you want to change the base?
fix: resolve URL path truncation in SSE transport for proxied servers #1211
Conversation
Hi @Kludex!... Can you please review this... |
- With root_path="/api" and endpoint="/messages/": Final path = "/api/messages/" | ||
- With root_path="/api" and endpoint="messages/": Final path = "/api/messages/" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The behavior I saw was: urllib.join("http://example.com/some/path", "/messages/")
resulted in http://example.com/messages
. I think it would be sufficient to just drop the leading forward slash sense that leads to an unexpected behavior. I would argue that the sdk should not be forcing its route to be at any particular location and that a dev should decide where it gets mounted. Relative path joining should allow that. See comment below for test cases
valid_endpoints_and_expected = [ | ||
("/messages/", "/messages/"), # Absolute path format | ||
("messages/", "messages/"), # Relative path format | ||
("/api/v1/messages/", "/api/v1/messages/"), | ||
("api/v1/messages/", "api/v1/messages/"), | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is the behavior demonstrated with examples:
>>> from urllib.parse import urljoin
>>>
>>> urljoin("http://www.google.com/hello/world", "/messages")
'http://www.google.com/messages'
>>> urljoin("http://www.google.com/hello/world", "messages")
'http://www.google.com/hello/messages'
>>> urljoin("http://www.google.com/hello/world/", "messages")
'http://www.google.com/hello/world/messages'
>>> urljoin("http://www.google.com/hello/world/", "/messages")
'http://www.google.com/messages'
>>> urljoin("http://www.google.com/hello/world/", "/messages/")
'http://www.google.com/messages/'
>>> urljoin("http://www.google.com/hello/world/", "messages/")
'http://www.google.com/hello/world/messages/'
>>> urljoin("http://www.google.com/hello/world", "messages/")
'http://www.google.com/hello/messages/'
urllib has some odd behavior imo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this is the one we want to coerce/enforce:
>>> urljoin("http://www.google.com/hello/world/", "messages/")
'http://www.google.com/hello/world/messages/'
Summary
Fixed URL path truncation issue in SSE server transport when using
urllib.parse.urljoin()
with servers behind proxies or mounted at subpaths.Motivation and Context
This change fixes issue #200 where
urllib.parse.urljoin()
was truncating server URL paths when combining base URLs with endpoints that have leading slashes. For example, joininghttp://localhost:8000/some/path/to/sse
with/messages/
would incorrectly outputhttp://localhost:8000/messages/
instead ofhttp://localhost:8000/some/path/to/sse/messages/
. This was particularly problematic for servers behind proxies or mounted at subpaths.How Has This Been Tested?
/messages/
) and relative (messages/
) endpoint formatsBreaking Changes
No breaking changes. The fix maintains backward compatibility:
SseServerTransport("/messages/")
continues to work unchangedSseServerTransport("messages/")
is now recommended for proxied serversChecklist
Additional context
Key changes made:
/messages/
andmessages/
formats_build_message_path()
helper method - intelligently constructs paths based on endpoint formatTechnical details:
urllib.parse.urljoin("http://host/path", "/messages/")
treats/messages/
as an absolute path, replacing the entire path portionmessages/
) when possible, which get properly appended:urllib.parse.urljoin("http://host/path/", "messages/")
→http://host/path/messages/
Resolves: #200