github.py 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import requests
  2. from fastapi import APIRouter, HTTPException, Request
  3. from fastapi.responses import JSONResponse
  4. from openhands.server.shared import openhands_config
  5. from openhands.utils.async_utils import call_sync_from_async
  6. app = APIRouter(prefix='/api')
  7. @app.get('/github/repositories')
  8. async def get_github_repositories(
  9. request: Request,
  10. page: int = 1,
  11. per_page: int = 10,
  12. sort: str = 'pushed',
  13. installation_id: int | None = None,
  14. ):
  15. # Extract the GitHub token from the headers
  16. github_token = request.headers.get('X-GitHub-Token')
  17. if not github_token:
  18. raise HTTPException(status_code=400, detail='Missing X-GitHub-Token header')
  19. openhands_config.verify_github_repo_list(installation_id)
  20. # Add query parameters
  21. params: dict[str, str] = {
  22. 'page': str(page),
  23. 'per_page': str(per_page),
  24. }
  25. # Construct the GitHub API URL
  26. if installation_id:
  27. github_api_url = (
  28. f'https://api.github.com/user/installations/{installation_id}/repositories'
  29. )
  30. else:
  31. github_api_url = 'https://api.github.com/user/repos'
  32. params['sort'] = sort
  33. # Set the authorization header with the GitHub token
  34. headers = {
  35. 'Authorization': f'Bearer {github_token}',
  36. 'Accept': 'application/vnd.github.v3+json',
  37. }
  38. # Fetch repositories from GitHub
  39. try:
  40. response = await call_sync_from_async(
  41. requests.get, github_api_url, headers=headers, params=params
  42. )
  43. response.raise_for_status() # Raise an error for HTTP codes >= 400
  44. except requests.exceptions.RequestException as e:
  45. raise HTTPException(
  46. status_code=response.status_code if response else 500,
  47. detail=f'Error fetching repositories: {str(e)}',
  48. )
  49. # Create response with the JSON content
  50. json_response = JSONResponse(content=response.json())
  51. response.close()
  52. # Forward the Link header if it exists
  53. if 'Link' in response.headers:
  54. json_response.headers['Link'] = response.headers['Link']
  55. return json_response