Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@ USER app
EXPOSE 8000

HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
CMD curl -fsS "http://127.0.0.1:${PORT}/" || exit 1
CMD curl -fsS "http://127.0.0.1:${PORT}/health/" || exit 1

CMD ["/bin/sh", "-c", "exec gunicorn config.wsgi:application --bind 0.0.0.0:${PORT:-8000} --workers ${GUNICORN_WORKERS:-3} --access-logfile - --error-logfile -"]
2 changes: 2 additions & 0 deletions config/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@

from django.contrib import admin
from django.urls import path
from .views import health_check

urlpatterns = [
path("health/", health_check, name="health_check"),
path("admin/", admin.site.urls),
]
21 changes: 21 additions & 0 deletions config/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from django.http import JsonResponse
from django.db import connection
from django.views.decorators.http import require_GET
import logging

logger = logging.getLogger(__name__)


Comment on lines +3 to +8
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The health check endpoint should be exempted from CSRF protection. Health check endpoints are typically called by monitoring systems, load balancers, and Docker/Kubernetes health checkers that don't have CSRF tokens. While @require_GET prevents modifications, the CSRF middleware will still reject requests without proper tokens.

Add @csrf_exempt decorator before @require_GET:

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
@require_GET
def health_check(request):
Suggested change
from django.views.decorators.http import require_GET
import logging
logger = logging.getLogger(__name__)
from django.views.decorators.http import require_GET
from django.views.decorators.csrf import csrf_exempt
import logging
logger = logging.getLogger(__name__)
@csrf_exempt

Copilot uses AI. Check for mistakes.
@require_GET
def health_check(request):
try:
with connection.cursor() as cursor:
cursor.execute("SELECT 1")
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] While executing "SELECT 1" verifies database connectivity, consider fetching the result with cursor.fetchone() to ensure the query completes fully. This provides a more thorough health check:

cursor.execute("SELECT 1")
cursor.fetchone()
Suggested change
cursor.execute("SELECT 1")
cursor.execute("SELECT 1")
cursor.fetchone()

Copilot uses AI. Check for mistakes.
cursor.fetchone()

return JsonResponse({"status": "healthy", "database": "connected"})
except Exception as e:
logger.error("Health check failed: %s", str(e), exc_info=True)
return JsonResponse(
{"status": "unhealthy", "database": "disconnected"}, status=503
)
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ services:
volumes:
- static-data:/app/static
healthcheck:
test: ["CMD", "curl", "-fsSL", "http://127.0.0.1:8000/"]
test: ["CMD", "curl", "-fsSL", "http://127.0.0.1:8000/health/"]
interval: 30s
timeout: 5s
retries: 3
Expand Down
6 changes: 0 additions & 6 deletions main.py

This file was deleted.