Я развернул статический сайт в корзине aws s3, URL-адрес которого выглядит следующим образом:
https://{bucket_name}.s3.{zone}.amazonaws.com/website/{ID}/index.html
и я хочу перенаправить весь трафик, попадающий на сервер, должен быть перенаправлен в корзину s3 вот так:
username.localhost:9000 -> https://{bucket_name}.s3.{zone}.amazonaws.com/website/{username}/index.html
если у вас есть какие-либо предложения от nginx, пожалуйста, поделитесь
Я попробовал решение -
import uvicorn
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import StreamingResponse
import httpx
import boto3
app = FastAPI()
S3_BUCKET_NAME = ${bucket}
async def proxy_request(request: Request):
s3_client = boto3.client('s3')
# Construct the S3 object key based on your requirements
x = request.url.path.split("/")[-2:]
y = '/'.join(x)
s3_key = f"website/{y}"
try:
# Get the object from S3
response = s3_client.get_object(Bucket=S3_BUCKET_NAME, Key=s3_key)
except s3_client.exceptions.NoSuchKey:
raise HTTPException(status_code=404, detail = "Object not found")
# Return the S3 object's content back to the client
return StreamingResponse(
content=response['Body'].iter_chunks(),
status_code=200,
headers = {"Content-Type": response['ContentType']},
)
@app.middleware("http")
async def proxy_middleware(request: Request, call_next):
try:
return await proxy_request(request)
except HTTPException as exc:
return exc
if __name__ == "__main__":
uvicorn.run(app, host = "127.0.0.1", port=9000)






Вы просите решения, которые фундаментально отличаются друг от друга. В вашем резюме указано прокси, но в описании указано перенаправление. Кроме того, ваш URL-адрес локального хоста имеет поддомен, который можно использовать только в том случае, если он сопоставлен в файле записи вашего хоста. Я постараюсь охватить варианты использования перенаправления/перенаправления s3 на локальном хосте.
Если все, что вам нужно, это простое перенаправление,
@app.route('/{_:path}')
async def s3_redirect(request: Request) -> RedirectResponse:
# return RedirectResponse(request.url.replace()) # If you want to retain the path/query params
return RedirectResponse("https://{bucket_name}.s3.{zone}.amazonaws.com/website/{username}/index.html")
Если вы ищете решение с помощью nginx, следующая конфигурация должна помочь
server {
listen 9000;
location / {
proxy_pass {s3_website};
}
# more locations to different endpoints
}
Я бы предпочел nginx или эквивалентное прокси-приложение использованию FastAPI, если вариант использования — просто прокси. Однако, если вы все еще хотите использовать FastAPI, я бы использовал несколько обширное решение, подобное приведенному ниже. Следующий пример будет действовать как базовый прокси-сервис. Вам не нужно будет проверять наличие объектов корзины, поскольку клиент httpx попытается достичь конечной точки s3 и ответить соответствующим образом.
Обратите внимание, что для использования этого решения ваши объекты корзины должны быть общедоступны.
import logging
from http import HTTPStatus
import httpx
import uvicorn.logging
from fastapi import FastAPI, HTTPException, Request, Response
from fastapi.routing import APIRoute
TARGET_URL = "http://127.0.0.1:8080" # Change this to the URL you want to proxy requests to
async def proxy(request: Request) -> Response:
"""Proxy handler function to forward incoming requests to a target URL.
Args:
request: The incoming request object.
Returns:
Response: The response object with the forwarded content and headers.
"""
try:
async with httpx.AsyncClient() as client:
body = await request.body()
# noinspection PyTypeChecker
response = await client.request(
method=request.method,
url=TARGET_URL + request.url.path,
headers=dict(request.headers),
cookies=request.cookies,
params=dict(request.query_params),
data=body.decode(),
)
# If the response content-type is text/html, we need to rewrite links in it
content_type = response.headers.get("content-type", "")
if "text/html" in content_type:
content = response.text
# Modify content if necessary (e.g., rewriting links)
# content = modify_html_links(content)
else:
content = response.content
response.headers.pop("content-encoding", None)
return Response(content, response.status_code, response.headers, content_type)
except httpx.RequestError as exc:
logging.getLogger("uvicorn.error").error(exc)
raise HTTPException(status_code=HTTPStatus.BAD_GATEWAY.value, detail=HTTPStatus.BAD_GATEWAY.phrase)
if __name__ == '__main__':
uvicorn.run(
app=FastAPI(
routes=[
APIRoute("/{_:path}", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"], endpoint=proxy)
]
)
)