jiangxt2 opened a new issue, #13735:
URL: https://github.com/apache/gravitino/issues/13735

   ### Version
   
   Python client 1.3.1 and Gravitino server 1.3.1. The same shared-header 
update is present on the main branch.
   
   ### Describe what's wrong
   
   Per-request headers passed to `HTTPClient.get(..., headers=...)` are merged 
into the client's persistent `request_headers` dictionary. A later request that 
supplies no headers still sends headers from the preceding request.
   
   This affects the public Fileset API: `get_file_location()` removes the 
thread-local CallerContext after a call, but its headers remain in the 
underlying HTTP client. After a lookup with `FilesetDataOperation: RENAME`, an 
ordinary lookup can therefore be treated as another rename operation and fail.
   
   Expected behavior: configured default headers persist, while headers 
supplied for one request apply only to that request.
   
   ### Error message and/or stacktrace
   
   For a managed Fileset root lookup, the leaked RENAME context causes HTTP 500 
and the following SDK exception:
   
   ```text
   InternalError: Failed to operate object [fileset] operation [GET] under 
[schema], reason [subPath cannot be blank when need to rename a file or a 
directory.]
   ```
   
   The same ordinary lookup succeeds with a fresh client.
   
   ### How to reproduce
   
   Start a Gravitino 1.3.1 server at `http://localhost:8090` and install 
`apache-gravitino==1.3.1`. The transport-level problem can be reproduced with 
two real requests:
   
   ```python
   from gravitino.utils.http_client import HTTPClient
   
   defaults = {"X-Test-Default": "default-value"}
   client = HTTPClient("http://localhost:8090";, request_headers=defaults)
   client.get("api/version", headers={"X-Test-Per-Request": "request-one"})
   client.get("api/version")
   print(client.request_headers["X-Test-Per-Request"])
   print(defaults["X-Test-Per-Request"])
   ```
   
   Both prints produce `request-one`. Capturing the requests shows that the 
second request also sends `X-Test-Per-Request: request-one`, even though it did 
not supply that header.
   
   For the public API consequence:
   
   1. Create a Hadoop-backed FILESET catalog, a schema, and a managed Fileset. 
Load its Fileset catalog once and call `get_file_location(ident, "")` without a 
CallerContext: the root location is returned.
   2. Set `CallerContextHolder.set(CallerContext({"FilesetDataOperation": 
"RENAME"}))` and call `get_file_location(ident, "")`. The rename of the root is 
correctly rejected.
   3. Confirm `CallerContextHolder.get() is None`, then repeat 
`get_file_location(ident, "")` on the same catalog object without setting a 
context. It still sends the RENAME header and fails.
   4. Load the catalog with a fresh GravitinoClient and repeat the ordinary 
lookup: it succeeds.
   
   ### Additional context
   
   With a real SDK/server pair in Docker, the four Fileset requests returned 
HTTP 200, 500, 500, and 200 respectively. The observed operation headers were 
absent, RENAME, RENAME, and absent. No concurrent calls are needed to trigger 
the problem.
   
   The affected paths are 
`clients/client-python/gravitino/utils/http_client.py` and the CallerContext 
forwarding in `clients/client-python/gravitino/client/fileset_catalog.py`. This 
report concerns request isolation; it does not claim an authorization bypass.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to