Skip to content

Commit

Permalink
Merge branch 'main' into rb/hidden-feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
xingyaoww authored Oct 30, 2024
2 parents 3446ab7 + 3ae4bc0 commit ace3aae
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 36 deletions.
25 changes: 25 additions & 0 deletions docs/modules/usage/troubleshooting/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Check out [Notes for WSL on Windows Users](troubleshooting/windows) for some tro
* [404 Resource not found](#404-resource-not-found)
* [`make build` getting stuck on package installations](#make-build-getting-stuck-on-package-installations)
* [Sessions are not restored](#sessions-are-not-restored)
* [Connection to host.docker.internal timed out](#connection-to-host-docker-internal-timed-out)

### Unable to connect to Docker

Expand Down Expand Up @@ -153,3 +154,27 @@ should stay accepted.
```bash
EXPORT JWT_SECRET=A_CONST_VALUE
```
---
### Connection to host docker internal timed out
**Symptoms**
When you start the server using the docker command from the main [README](https://github.com/All-Hands-AI/OpenHands/README.md), you get a long timeout
followed by the a stack trace containing messages like:
* `Connection to host.docker.internal timed out. (connect timeout=310)`
* `Max retries exceeded with url: /alive`
**Details**
If Docker Engine is installed rather than Docker Desktop, the main command will not work as expected.
Docker Desktop includes easy DNS configuration for connecting processes running in different containers
which OpenHands makes use of when the main server is running inside a docker container.
(Further details: https://forums.docker.com/t/difference-between-docker-desktop-and-docker-engine/124612)
**Workarounds**
* [Install Docker Desktop](https://www.docker.com/products/docker-desktop/)
* Run OpenHands in [Development Mode](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md),
So that the main server is not run inside a container, but still creates dockerized runtime sandboxes.
22 changes: 2 additions & 20 deletions openhands/server/listen.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,10 @@
WebSocket,
status,
)
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse, StreamingResponse
from fastapi.security import HTTPBearer
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel
from starlette.middleware.base import BaseHTTPMiddleware

import openhands.agenthub # noqa F401 (we import this to get the agents registered)
from openhands.controller.agent import Agent
Expand All @@ -57,6 +55,7 @@
from openhands.llm import bedrock
from openhands.runtime.base import Runtime
from openhands.server.auth import get_sid_from_token, sign_token
from openhands.server.middleware import LocalhostCORSMiddleware, NoCacheMiddleware
from openhands.server.session import SessionManager

load_dotenv()
Expand Down Expand Up @@ -93,30 +92,13 @@ async def lifespan(app: FastAPI):

app = FastAPI(lifespan=lifespan)
app.add_middleware(
CORSMiddleware,
allow_origins=['http://localhost:3001', 'http://127.0.0.1:3001'],
LocalhostCORSMiddleware,
allow_credentials=True,
allow_methods=['*'],
allow_headers=['*'],
)


class NoCacheMiddleware(BaseHTTPMiddleware):
"""
Middleware to disable caching for all routes by adding appropriate headers
"""

async def dispatch(self, request, call_next):
response = await call_next(request)
if not request.url.path.startswith('/assets'):
response.headers['Cache-Control'] = (
'no-cache, no-store, must-revalidate, max-age=0'
)
response.headers['Pragma'] = 'no-cache'
response.headers['Expires'] = '0'
return response


app.add_middleware(NoCacheMiddleware)

security_scheme = HTTPBearer()
Expand Down
43 changes: 43 additions & 0 deletions openhands/server/middleware.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from urllib.parse import urlparse

from fastapi.middleware.cors import CORSMiddleware
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.types import ASGIApp


class LocalhostCORSMiddleware(CORSMiddleware):
"""
Custom CORS middleware that allows any request from localhost/127.0.0.1 domains,
while using standard CORS rules for other origins.
"""

def __init__(self, app: ASGIApp, **kwargs) -> None:
super().__init__(app, **kwargs)

async def is_allowed_origin(self, origin: str) -> bool:
if origin:
parsed = urlparse(origin)
hostname = parsed.hostname or ''

# Allow any localhost/127.0.0.1 origin regardless of port
if hostname in ['localhost', '127.0.0.1']:
return True

# For missing origin or other origins, use the parent class's logic
return await super().is_allowed_origin(origin)


class NoCacheMiddleware(BaseHTTPMiddleware):
"""
Middleware to disable caching for all routes by adding appropriate headers
"""

async def dispatch(self, request, call_next):
response = await call_next(request)
if not request.url.path.startswith('/assets'):
response.headers['Cache-Control'] = (
'no-cache, no-store, must-revalidate, max-age=0'
)
response.headers['Pragma'] = 'no-cache'
response.headers['Expires'] = '0'
return response
26 changes: 11 additions & 15 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ packages = [
python = "^3.12"
datasets = "*"
pandas = "*"
litellm = { git = "https://github.com/BerriAI/litellm.git", rev = "58fe6610601297c5a90367fd4583469e2df3fcf9" }
litellm = "^1.51.1"
google-generativeai = "*" # To use litellm with Gemini Pro API
termcolor = "*"
seaborn = "*"
Expand Down

0 comments on commit ace3aae

Please sign in to comment.