mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-08-30 11:49:38 +02:00
sdk: allow specifying run time headers in http client (#4000)
This PR only allows this in the HTTP client. I can follow up with a PR to allow throughout the entire API. The use case is to allow instantiating the client once (w/ a single connection pool), but allowing changing api keys and any other headers at run time
This commit is contained in:
@@ -208,9 +208,15 @@ class HttpClient:
|
||||
def __init__(self, client: httpx.AsyncClient) -> None:
|
||||
self.client = client
|
||||
|
||||
async def get(self, path: str, *, params: Optional[QueryParamTypes] = None) -> Any:
|
||||
async def get(
|
||||
self,
|
||||
path: str,
|
||||
*,
|
||||
params: Optional[QueryParamTypes] = None,
|
||||
headers: Optional[dict[str, str]] = None,
|
||||
) -> Any:
|
||||
"""Send a GET request."""
|
||||
r = await self.client.get(path, params=params)
|
||||
r = await self.client.get(path, params=params, headers=headers)
|
||||
try:
|
||||
r.raise_for_status()
|
||||
except httpx.HTTPStatusError as e:
|
||||
@@ -222,13 +228,22 @@ class HttpClient:
|
||||
raise e
|
||||
return await adecode_json(r)
|
||||
|
||||
async def post(self, path: str, *, json: Optional[dict]) -> Any:
|
||||
async def post(
|
||||
self,
|
||||
path: str,
|
||||
*,
|
||||
json: Optional[dict],
|
||||
headers: Optional[dict[str, str]] = None,
|
||||
) -> Any:
|
||||
"""Send a POST request."""
|
||||
if json is not None:
|
||||
headers, content = await aencode_json(json)
|
||||
request_headers, content = await aencode_json(json)
|
||||
else:
|
||||
headers, content = {}, b""
|
||||
r = await self.client.post(path, headers=headers, content=content)
|
||||
request_headers, content = {}, b""
|
||||
# Merge headers, with runtime headers taking precedence
|
||||
if headers:
|
||||
request_headers.update(headers)
|
||||
r = await self.client.post(path, headers=request_headers, content=content)
|
||||
try:
|
||||
r.raise_for_status()
|
||||
except httpx.HTTPStatusError as e:
|
||||
@@ -240,10 +255,14 @@ class HttpClient:
|
||||
raise e
|
||||
return await adecode_json(r)
|
||||
|
||||
async def put(self, path: str, *, json: dict) -> Any:
|
||||
async def put(
|
||||
self, path: str, *, json: dict, headers: Optional[dict[str, str]] = None
|
||||
) -> Any:
|
||||
"""Send a PUT request."""
|
||||
headers, content = await aencode_json(json)
|
||||
r = await self.client.put(path, headers=headers, content=content)
|
||||
request_headers, content = await aencode_json(json)
|
||||
if headers:
|
||||
request_headers.update(headers)
|
||||
r = await self.client.put(path, headers=request_headers, content=content)
|
||||
try:
|
||||
r.raise_for_status()
|
||||
except httpx.HTTPStatusError as e:
|
||||
@@ -255,10 +274,14 @@ class HttpClient:
|
||||
raise e
|
||||
return await adecode_json(r)
|
||||
|
||||
async def patch(self, path: str, *, json: dict) -> Any:
|
||||
async def patch(
|
||||
self, path: str, *, json: dict, headers: Optional[dict[str, str]] = None
|
||||
) -> Any:
|
||||
"""Send a PATCH request."""
|
||||
headers, content = await aencode_json(json)
|
||||
r = await self.client.patch(path, headers=headers, content=content)
|
||||
request_headers, content = await aencode_json(json)
|
||||
if headers:
|
||||
request_headers.update(headers)
|
||||
r = await self.client.patch(path, headers=request_headers, content=content)
|
||||
try:
|
||||
r.raise_for_status()
|
||||
except httpx.HTTPStatusError as e:
|
||||
@@ -270,9 +293,15 @@ class HttpClient:
|
||||
raise e
|
||||
return await adecode_json(r)
|
||||
|
||||
async def delete(self, path: str, *, json: Optional[Any] = None) -> None:
|
||||
async def delete(
|
||||
self,
|
||||
path: str,
|
||||
*,
|
||||
json: Optional[Any] = None,
|
||||
headers: Optional[dict[str, str]] = None,
|
||||
) -> None:
|
||||
"""Send a DELETE request."""
|
||||
r = await self.client.request("DELETE", path, json=json)
|
||||
r = await self.client.request("DELETE", path, json=json, headers=headers)
|
||||
try:
|
||||
r.raise_for_status()
|
||||
except httpx.HTTPStatusError as e:
|
||||
@@ -290,14 +319,18 @@ class HttpClient:
|
||||
*,
|
||||
json: Optional[dict] = None,
|
||||
params: Optional[QueryParamTypes] = None,
|
||||
headers: Optional[dict[str, str]] = None,
|
||||
) -> AsyncIterator[StreamPart]:
|
||||
"""Stream results using SSE."""
|
||||
headers, content = await aencode_json(json)
|
||||
headers["Accept"] = "text/event-stream"
|
||||
headers["Cache-Control"] = "no-store"
|
||||
request_headers, content = await aencode_json(json)
|
||||
request_headers["Accept"] = "text/event-stream"
|
||||
request_headers["Cache-Control"] = "no-store"
|
||||
# Add runtime headers with precedence
|
||||
if headers:
|
||||
request_headers.update(headers)
|
||||
|
||||
async with self.client.stream(
|
||||
method, path, headers=headers, content=content, params=params
|
||||
method, path, headers=request_headers, content=content, params=params
|
||||
) as res:
|
||||
# check status
|
||||
try:
|
||||
@@ -2447,9 +2480,15 @@ class SyncHttpClient:
|
||||
def __init__(self, client: httpx.Client) -> None:
|
||||
self.client = client
|
||||
|
||||
def get(self, path: str, *, params: Optional[QueryParamTypes] = None) -> Any:
|
||||
def get(
|
||||
self,
|
||||
path: str,
|
||||
*,
|
||||
params: Optional[QueryParamTypes] = None,
|
||||
headers: Optional[dict[str, str]] = None,
|
||||
) -> Any:
|
||||
"""Send a GET request."""
|
||||
r = self.client.get(path, params=params)
|
||||
r = self.client.get(path, params=params, headers=headers)
|
||||
try:
|
||||
r.raise_for_status()
|
||||
except httpx.HTTPStatusError as e:
|
||||
@@ -2461,13 +2500,21 @@ class SyncHttpClient:
|
||||
raise e
|
||||
return decode_json(r)
|
||||
|
||||
def post(self, path: str, *, json: Optional[dict]) -> Any:
|
||||
def post(
|
||||
self,
|
||||
path: str,
|
||||
*,
|
||||
json: Optional[dict],
|
||||
headers: Optional[dict[str, str]] = None,
|
||||
) -> Any:
|
||||
"""Send a POST request."""
|
||||
if json is not None:
|
||||
headers, content = encode_json(json)
|
||||
request_headers, content = encode_json(json)
|
||||
else:
|
||||
headers, content = {}, b""
|
||||
r = self.client.post(path, headers=headers, content=content)
|
||||
request_headers, content = {}, b""
|
||||
if headers:
|
||||
request_headers.update(headers)
|
||||
r = self.client.post(path, headers=request_headers, content=content)
|
||||
try:
|
||||
r.raise_for_status()
|
||||
except httpx.HTTPStatusError as e:
|
||||
@@ -2494,10 +2541,14 @@ class SyncHttpClient:
|
||||
raise e
|
||||
return decode_json(r)
|
||||
|
||||
def patch(self, path: str, *, json: dict) -> Any:
|
||||
def patch(
|
||||
self, path: str, *, json: dict, headers: Optional[dict[str, str]] = None
|
||||
) -> Any:
|
||||
"""Send a PATCH request."""
|
||||
headers, content = encode_json(json)
|
||||
r = self.client.patch(path, headers=headers, content=content)
|
||||
request_headers, content = encode_json(json)
|
||||
if headers:
|
||||
request_headers.update(headers)
|
||||
r = self.client.patch(path, headers=request_headers, content=content)
|
||||
try:
|
||||
r.raise_for_status()
|
||||
except httpx.HTTPStatusError as e:
|
||||
@@ -2509,9 +2560,15 @@ class SyncHttpClient:
|
||||
raise e
|
||||
return decode_json(r)
|
||||
|
||||
def delete(self, path: str, *, json: Optional[Any] = None) -> None:
|
||||
def delete(
|
||||
self,
|
||||
path: str,
|
||||
*,
|
||||
json: Optional[Any] = None,
|
||||
headers: Optional[dict[str, str]] = None,
|
||||
) -> None:
|
||||
"""Send a DELETE request."""
|
||||
r = self.client.request("DELETE", path, json=json)
|
||||
r = self.client.request("DELETE", path, json=json, headers=headers)
|
||||
try:
|
||||
r.raise_for_status()
|
||||
except httpx.HTTPStatusError as e:
|
||||
@@ -2529,11 +2586,16 @@ class SyncHttpClient:
|
||||
*,
|
||||
json: Optional[dict] = None,
|
||||
params: Optional[QueryParamTypes] = None,
|
||||
headers: Optional[dict[str, str]] = None,
|
||||
) -> Iterator[StreamPart]:
|
||||
"""Stream the results of a request using SSE."""
|
||||
headers, content = encode_json(json)
|
||||
request_headers, content = encode_json(json)
|
||||
request_headers["Accept"] = "text/event-stream"
|
||||
request_headers["Cache-Control"] = "no-store"
|
||||
if headers:
|
||||
request_headers.update(headers)
|
||||
with self.client.stream(
|
||||
method, path, headers=headers, content=content, params=params
|
||||
method, path, headers=request_headers, content=content, params=params
|
||||
) as res:
|
||||
# check status
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user