...
This commit is contained in:
		
							
								
								
									
										89
									
								
								app/api/connection-details/route.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								app/api/connection-details/route.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,89 @@
 | 
			
		||||
import { randomString } from '@/lib/client-utils';
 | 
			
		||||
import { getLiveKitURL } from '@/lib/getLiveKitURL';
 | 
			
		||||
import { ConnectionDetails } from '@/lib/types';
 | 
			
		||||
import { AccessToken, AccessTokenOptions, VideoGrant } from 'livekit-server-sdk';
 | 
			
		||||
import { NextRequest, NextResponse } from 'next/server';
 | 
			
		||||
 | 
			
		||||
const API_KEY = process.env.LIVEKIT_API_KEY;
 | 
			
		||||
const API_SECRET = process.env.LIVEKIT_API_SECRET;
 | 
			
		||||
const LIVEKIT_URL = process.env.LIVEKIT_URL;
 | 
			
		||||
 | 
			
		||||
const COOKIE_KEY = 'random-participant-postfix';
 | 
			
		||||
 | 
			
		||||
export async function GET(request: NextRequest) {
 | 
			
		||||
  try {
 | 
			
		||||
    // Parse query parameters
 | 
			
		||||
    const roomName = request.nextUrl.searchParams.get('roomName');
 | 
			
		||||
    const participantName = request.nextUrl.searchParams.get('participantName');
 | 
			
		||||
    const metadata = request.nextUrl.searchParams.get('metadata') ?? '';
 | 
			
		||||
    const region = request.nextUrl.searchParams.get('region');
 | 
			
		||||
    if (!LIVEKIT_URL) {
 | 
			
		||||
      throw new Error('LIVEKIT_URL is not defined');
 | 
			
		||||
    }
 | 
			
		||||
    const livekitServerUrl = region ? getLiveKitURL(LIVEKIT_URL, region) : LIVEKIT_URL;
 | 
			
		||||
    let randomParticipantPostfix = request.cookies.get(COOKIE_KEY)?.value;
 | 
			
		||||
    if (livekitServerUrl === undefined) {
 | 
			
		||||
      throw new Error('Invalid region');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (typeof roomName !== 'string') {
 | 
			
		||||
      return new NextResponse('Missing required query parameter: roomName', { status: 400 });
 | 
			
		||||
    }
 | 
			
		||||
    if (participantName === null) {
 | 
			
		||||
      return new NextResponse('Missing required query parameter: participantName', { status: 400 });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Generate participant token
 | 
			
		||||
    if (!randomParticipantPostfix) {
 | 
			
		||||
      randomParticipantPostfix = randomString(4);
 | 
			
		||||
    }
 | 
			
		||||
    const participantToken = await createParticipantToken(
 | 
			
		||||
      {
 | 
			
		||||
        identity: `${participantName}__${randomParticipantPostfix}`,
 | 
			
		||||
        name: participantName,
 | 
			
		||||
        metadata,
 | 
			
		||||
      },
 | 
			
		||||
      roomName,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // Return connection details
 | 
			
		||||
    const data: ConnectionDetails = {
 | 
			
		||||
      serverUrl: livekitServerUrl,
 | 
			
		||||
      roomName: roomName,
 | 
			
		||||
      participantToken: participantToken,
 | 
			
		||||
      participantName: participantName,
 | 
			
		||||
    };
 | 
			
		||||
    return new NextResponse(JSON.stringify(data), {
 | 
			
		||||
      headers: {
 | 
			
		||||
        'Content-Type': 'application/json',
 | 
			
		||||
        'Set-Cookie': `${COOKIE_KEY}=${randomParticipantPostfix}; Path=/; HttpOnly; SameSite=Strict; Secure; Expires=${getCookieExpirationTime()}`,
 | 
			
		||||
      },
 | 
			
		||||
    });
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    if (error instanceof Error) {
 | 
			
		||||
      return new NextResponse(error.message, { status: 500 });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function createParticipantToken(userInfo: AccessTokenOptions, roomName: string) {
 | 
			
		||||
  const at = new AccessToken(API_KEY, API_SECRET, userInfo);
 | 
			
		||||
  at.ttl = '5m';
 | 
			
		||||
  const grant: VideoGrant = {
 | 
			
		||||
    room: roomName,
 | 
			
		||||
    roomJoin: true,
 | 
			
		||||
    canPublish: true,
 | 
			
		||||
    canPublishData: true,
 | 
			
		||||
    canSubscribe: true,
 | 
			
		||||
  };
 | 
			
		||||
  at.addGrant(grant);
 | 
			
		||||
  return at.toJwt();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getCookieExpirationTime(): string {
 | 
			
		||||
  var now = new Date();
 | 
			
		||||
  var time = now.getTime();
 | 
			
		||||
  var expireTime = time + 60 * 120 * 1000;
 | 
			
		||||
  now.setTime(expireTime);
 | 
			
		||||
  return now.toUTCString();
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user