结构
Solr诉9.8.0,3节点我需要将我的RESTAPI请求发送到Solr,以便我可以搜索内容。 为此,我使用pysolr.
问题
当我以auth参数给定令牌发送请求时,我总是会得到一个“ typeError:'str”对象是不可callable的“错误”错误。
我尝试了什么 i首先尝试了我的功能,而无需进行身份验证,该验证可以按预期返回我的搜索结果。然后,我尝试使用一个静态令牌,该令牌返回错误。最后,我尝试了一个总是新生成的令牌,还返回了错误。由于我不确定生成的令牌作品是否在控制台中打印了令牌,并试图与邮递员一起发送带有给定令牌的请求。 当我使用用户名和密码使用“基本身份验证”时,它也可以工作。
我期望的是什么 我希望,该请求已发送到Solr。然后,Solr应该检查JWT令牌是否有效,并在Security.json中设置的设置。 代码from typing import Any
import jwt
import pysolr
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi_cache.decorator import cache
from app.caching import TTL
from app.core.config import settings
from app.models import SearchResults
from app.queryparams import SearchQueryParams
from app.utils import check_search_input
router = APIRouter()
@router.get("/", response_model=SearchResults)
# @cache(expire=TTL.WEEK, namespace="public:search")
async def search(
skip: int = 0,
limit: int = 100,
params: SearchQueryParams = Depends(),
) -> Any:
"""
Search query.
"""
if not check_search_input(params=params):
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail="Mindestens ein Feld muss ausgefüllt werden",
)
zookeeper = pysolr.ZooKeeper("search-zoo1,search-zoo2,search-zoo3")
jwt_token = jwt.encode({
"sub": "test-backend",
"name": "test-backend",
"iat": 1516239022,
"admin": False,
"iss": "test-solr-auth",
"solr": "test-backend",
"aud": "test-solr-api",
"exp": 33292598400,
"scope": "test-backend",
"realm": "test-solr-jwt"
}, settings.KEY, algorithm="RS256")
solr = pysolr.SolrCloud(zookeeper, "tag", auth=jwt_token)
res = solr.search(q=params.query, start=skip, rows=limit)
return SearchResults(data=res, count=res.hits)
ErrorTrackback
INFO: "GET /v1/search/?skip=0&limit=100&query=title%3A%22Yellow%22&descending=false HTTP/1.1" 500 Internal Server Error
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "/app/.venv/lib/python3.13/site-packages/uvicorn/protocols/http/httptools_impl.py", line 401, in run_asgi
result = await app( # type: ignore[func-returns-value]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
self.scope, self.receive, self.send
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "/app/.venv/lib/python3.13/site-packages/uvicorn/middleware/proxy_headers.py", line 60, in __call__
return await self.app(scope, receive, send)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/app/.venv/lib/python3.13/site-packages/fastapi/applications.py", line 1054, in __call__
await super().__call__(scope, receive, send)
File "/app/.venv/lib/python3.13/site-packages/starlette/applications.py", line 113, in __call__
await self.middleware_stack(scope, receive, send)
File "/app/.venv/lib/python3.13/site-packages/starlette/middleware/errors.py", line 187, in __call__
raise exc
File "/app/.venv/lib/python3.13/site-packages/starlette/middleware/errors.py", line 165, in __call__
await self.app(scope, receive, _send)
File "/app/.venv/lib/python3.13/site-packages/starlette/middleware/cors.py", line 93, in __call__
await self.simple_response(scope, receive, send, request_headers=headers)
File "/app/.venv/lib/python3.13/site-packages/starlette/middleware/cors.py", line 144, in simple_response
await self.app(scope, receive, send)
File "/app/.venv/lib/python3.13/site-packages/starlette/middleware/exceptions.py", line 62, in __call__
await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
File "/app/.venv/lib/python3.13/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
raise exc
File "/app/.venv/lib/python3.13/site-packages/starlette/_exception_handler.py", line 42, in wrapped_app
await app(scope, receive, sender)
File "/app/.venv/lib/python3.13/site-packages/starlette/routing.py", line 715, in __call__
await self.middleware_stack(scope, receive, send)
File "/app/.venv/lib/python3.13/site-packages/starlette/routing.py", line 735, in app
await route.handle(scope, receive, send)
File "/app/.venv/lib/python3.13/site-packages/starlette/routing.py", line 288, in handle
await self.app(scope, receive, send)
File "/app/.venv/lib/python3.13/site-packages/starlette/routing.py", line 76, in app
await wrap_app_handling_exceptions(app, request)(scope, receive, send)
File "/app/.venv/lib/python3.13/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
raise exc
File "/app/.venv/lib/python3.13/site-packages/starlette/_exception_handler.py", line 42, in wrapped_app
await app(scope, receive, sender)
File "/app/.venv/lib/python3.13/site-packages/starlette/routing.py", line 73, in app
response = await f(request)
^^^^^^^^^^^^^^^^
File "/app/.venv/lib/python3.13/site-packages/fastapi/routing.py", line 301, in app
raw_response = await run_endpoint_function(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...<3 lines>...
)
^
File "/app/.venv/lib/python3.13/site-packages/fastapi/routing.py", line 212, in run_endpoint_function
return await dependant.call(**values)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/app/app/api/routes/public/search.py", line 56, in search
res = solr.search(q=params.query, start=skip, rows=limit)
File "/app/.venv/lib/python3.13/site-packages/pysolr.py", line 834, in search
response = self._select(params, handler=search_handler)
File "/app/.venv/lib/python3.13/site-packages/pysolr.py", line 486, in _select
return self._send_request("get", path)
~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
File "/app/.venv/lib/python3.13/site-packages/pysolr.py", line 1512, in _send_request
return Solr._send_request(self, method, path, body, headers, files)
~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/app/.venv/lib/python3.13/site-packages/pysolr.py", line 414, in _send_request
resp = requests_method(
url,
...<4 lines>...
auth=self.auth,
)
File "/app/.venv/lib/python3.13/site-packages/requests/sessions.py", line 602, in get
return self.request("GET", url, **kwargs)
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/app/.venv/lib/python3.13/site-packages/requests/sessions.py", line 575, in request
prep = self.prepare_request(req)
File "/app/.venv/lib/python3.13/site-packages/requests/sessions.py", line 484, in prepare_request
p.prepare(
~~~~~~~~~^
method=request.method.upper(),
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...<10 lines>...
hooks=merge_hooks(request.hooks, self.hooks),
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "/app/.venv/lib/python3.13/site-packages/requests/models.py", line 371, in prepare
self.prepare_auth(auth, url)
~~~~~~~~~~~~~~~~~^^^^^^^^^^^
File "/app/.venv/lib/python3.13/site-packages/requests/models.py", line 602, in prepare_auth
r = auth(self)
TypeError: 'str' object is not callable
因此,我找到了解决这个问题的解决方案。它可能不漂亮,但它起作用。
我所做的是,我创建了一个使用authbase类的名为“ jwtauth”的类。当我打电话给班级时,我通过令牌。这样,pysolr的auth参数将获得类而不是字符串,因此很高兴。class JWTAuth(AuthBase):
def __init__(self, jwt_token):
self.jwt_token = jwt_token
def __call__(self, r):
r.headers['Authorization'] = f'Bearer {self.jwt_token}'
return r
async def search(
skip: int = 0,
limit: int = 100,
params: SearchQueryParams = Depends(),
) -> Any:
"""
Search query.
"""
zookeeper = pysolr.ZooKeeper("search-zoo1,search-zoo2,search-zoo3")
solr = pysolr.SolrCloud(zookeeper, "tag", auth=JWTAuth(add-token-here))
res = solr.search(q=params.query, start=skip, rows=limit)
return SearchResults(data=res, count=res.hits)