Skip to content

Commit

Permalink
chore: add an nginx to compose so that user only needs to expose a si…
Browse files Browse the repository at this point in the history
…ngle port
  • Loading branch information
vieiralucas committed Sep 13, 2024
1 parent 0ee30a8 commit 42f9a80
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 22 deletions.
31 changes: 31 additions & 0 deletions apps/api/src/websocket/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ type Server = {
export function createSocketServer(server: http.Server): Server {
const io: IOServer = new BaseServer(server, {
cors: { credentials: true, origin: config().FRONTEND_URL },
transports: ['websocket'],
})

io.use(async (socket: Socket, next) => {
Expand All @@ -68,15 +69,31 @@ export function createSocketServer(server: http.Server): Server {
next(new Error('Unauthorized'))
}
} catch (err) {
logger.error(
{
err,
socketId: socket.id,
},
'Error authenticating socket connection'
)
next(new Error('Internal Server Error'))
}
})

let workInProgress: Map<string, Promise<void>> = new Map()

io.on('connection', (socket: Socket) => {
logger.info({ socketId: socket.id }, 'Client connected to socket server')

const session = socket.session
if (!session) {
logger.error(
{
socketId: socket.id,
},
'Socket connection did not have a session'
)

socket.disconnect(true)
return
}
Expand Down Expand Up @@ -104,6 +121,20 @@ export function createSocketServer(server: http.Server): Server {
trackWork(handleRestartEnvironment(socket, session))
)
socket.on('complete-python', trackWork(completePython(io, socket, session)))

socket.on('disconnect', (reason) => {
logger.info(
{ socketId: socket.id, reason },
'Client disconnected from socket server'
)
})

socket.on('error', (error) => {
logger.error(
{ socketId: socket.id, error },
'Socket server error occurred'
)
})
})

return {
Expand Down
3 changes: 1 addition & 2 deletions apps/api/src/yjs/v2/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,7 @@ async function getRequestData(req: http.IncomingMessage): Promise<{
} | null> {
const cookiesHeader = req.headers.cookie
const cookies = cookie.parse(cookiesHeader ?? '')
const url = new URL(req.url ?? '', config().API_URL)
const query = qs.parse(url.search.slice(1))
const query = qs.parse(req.url?.split('?')[1] ?? '')
const docId = query['documentId']
const clock = parseInt((query['clock'] ?? '').toString())
const isDataApp = query['isDataApp'] === 'true'
Expand Down
6 changes: 5 additions & 1 deletion apps/web/src/hooks/useWebsocket.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@ export function WebsocketProvider({ children }: Props) {
const workspaceId = useStringQuery('workspaceId')
useEffect(() => {
if (session.data) {
const socket = io(NEXT_PUBLIC_API_URL(), {
const url = new URL(NEXT_PUBLIC_API_URL())
const withoutPathname = url.origin
const socket = io(withoutPathname, {
withCredentials: true,
path: url.pathname + '/socket.io',
transports: ['websocket'],
})
setSocket(socket)

Expand Down
16 changes: 13 additions & 3 deletions apps/web/src/utils/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,24 @@ function getFromWindow(key: string, or?: string): string {
}
}

function currentUrl() {
return `${window.location.protocol}//${window.location.host}`
}

export const NEXT_PUBLIC_API_URL = () =>
process.env.NEXT_PUBLIC_API_URL || getFromWindow('NEXT_PUBLIC_API_URL')
process.env.NEXT_PUBLIC_API_URL ||
getFromWindow('NEXT_PUBLIC_API_URL') ||
`${currentUrl()}/api`

export const NEXT_PUBLIC_API_WS_URL = () =>
process.env.NEXT_PUBLIC_API_WS_URL || getFromWindow('NEXT_PUBLIC_API_WS_URL')
process.env.NEXT_PUBLIC_API_WS_URL ||
getFromWindow('NEXT_PUBLIC_API_WS_URL') ||
`${currentUrl().replace('http', 'ws')}/api`

export const NEXT_PUBLIC_PUBLIC_URL = () =>
process.env.NEXT_PUBLIC_PUBLIC_URL || getFromWindow('NEXT_PUBLIC_PUBLIC_URL')
process.env.NEXT_PUBLIC_PUBLIC_URL ||
getFromWindow('NEXT_PUBLIC_PUBLIC_URL') ||
currentUrl()

export const NEXT_PUBLIC_GATEWAY_IP = () =>
process.env.NEXT_PUBLIC_GATEWAY_IP ||
Expand Down
30 changes: 14 additions & 16 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -76,18 +76,8 @@ services:
build:
context: '.'
dockerfile: 'apps/web/Dockerfile'
args:
NODE_ENV: 'production'
NEXT_PUBLIC_API_URL: 'https://api.${TLD:?error}'
NEXT_PUBLIC_API_WS_URL: 'wss://api.${TLD:?error}'
NEXT_PUBLIC_PUBLIC_URL: 'https://app.${TLD:?error}'
environment:
NODE_ENV: 'production'
NEXT_PUBLIC_API_URL: 'https://api.${TLD:?error}'
NEXT_PUBLIC_API_WS_URL: 'wss://api.${TLD:?error}'
NEXT_PUBLIC_PUBLIC_URL: 'https://app.${TLD:?error}'
ports:
- '3000:3000'
depends_on:
api:
condition: service_healthy
Expand All @@ -97,14 +87,11 @@ services:
build:
context: '.'
dockerfile: 'apps/api/Dockerfile'
ports:
- '8080:8080'
environment:
NODE_ENV: 'production'
LOG_LEVEL: 'info'
API_URL: 'https://api.${TLD:?error}'
FRONTEND_URL: 'https://app.${TLD:?error}'
TLD: ${TLD:?error}
LOG_LEVEL: 'debug'
API_URL: '/api'
FRONTEND_URL: '/'
LOGIN_JWT_SECRET: ${LOGIN_JWT_SECRET:?error}
AUTH_JWT_SECRET: ${AUTH_JWT_SECRET:?error}
AI_API_URL: 'http://ai:8000'
Expand Down Expand Up @@ -138,6 +125,17 @@ services:
ai:
condition: service_healthy

nginx:
image: nginx:latest
depends_on:
- web
- api
ports:
- '3000:3000'
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
restart: always

volumes:
jupyter:
postgres_data:
71 changes: 71 additions & 0 deletions nginx/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
worker_processes 1;

events {
worker_connections 1024;
}

http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;

upstream web {
server web:3000;
}

upstream api {
server api:8080;
}

server {
listen 3000;

# Handle WebSocket connections for /api/socket.io
location /api/socket.io/ {
proxy_pass http://api/socket.io/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 60m;
proxy_send_timeout 60m;
proxy_buffering off; # Disable buffering for WebSocket
}

location /api/v2/yjs/ {
proxy_pass http://api/v2/yjs/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 60m;
proxy_send_timeout 60m;
proxy_buffering off; # Disable buffering for WebSocket
}

# Proxy regular HTTP requests to /api (non-WebSocket) to the API service
location /api/ {
proxy_pass http://api/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

# Proxy everything else to the frontend service
location / {
proxy_pass http://web/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}

0 comments on commit 42f9a80

Please sign in to comment.