Change env var names, add support for region query (#10)

This commit is contained in:
lukasIO 2023-01-20 15:41:00 +01:00 committed by GitHub
parent e234a76293
commit f4a301c116
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 75 additions and 30 deletions

View file

@ -5,7 +5,8 @@
LIVEKIT_API_KEY=devkey LIVEKIT_API_KEY=devkey
LIVEKIT_API_SECRET=secret LIVEKIT_API_SECRET=secret
# URL pointing to the LiveKit server.
LIVEKIT_URL=wss://my-livekit-project.livekit.cloud
## PUBLIC ## PUBLIC
NEXT_PUBLIC_LK_TOKEN_ENDPOINT=/api/token NEXT_PUBLIC_LK_TOKEN_ENDPOINT=/api/token
NEXT_PUBLIC_LK_SERVER_URL=wss://my-livekit-project.livekit.cloud

View file

@ -1,9 +1,9 @@
import * as React from 'react'; import * as React from 'react';
import { useRoomContext } from '@livekit/components-react'; import { useRoomContext } from '@livekit/components-react';
import { setLogLevel } from 'livekit-client'; import { setLogLevel, LogLevel } from 'livekit-client';
export const useDebugMode = () => { export const useDebugMode = ({ logLevel }: { logLevel?: LogLevel }) => {
setLogLevel('debug'); setLogLevel(logLevel ?? 'debug');
const room = useRoomContext(); const room = useRoomContext();
React.useEffect(() => { React.useEffect(() => {
// @ts-expect-error // @ts-expect-error
@ -16,7 +16,7 @@ export const useDebugMode = () => {
}); });
}; };
export const DebugMode = () => { export const DebugMode = ({ logLevel }: { logLevel?: LogLevel }) => {
useDebugMode(); useDebugMode({ logLevel });
return <></>; return <></>;
}; };

21
lib/client-utils.ts Normal file
View file

@ -0,0 +1,21 @@
import { useEffect, useState } from 'react';
export function useServerUrl(region?: string) {
const [serverUrl, setServerUrl] = useState<string | undefined>();
useEffect(() => {
let endpoint = `/api/url`;
if (region) {
endpoint += `?region=${region}`;
}
fetch(endpoint).then(async (res) => {
if (res.ok) {
const body = await res.json();
console.log(body);
setServerUrl(body.url);
} else {
throw Error('Error fetching server url, check server logs');
}
});
});
return serverUrl;
}

View file

@ -5,10 +5,10 @@ export function getRoomClient(): RoomServiceClient {
return new RoomServiceClient(getLiveKitURL()); return new RoomServiceClient(getLiveKitURL());
} }
export function getLiveKitURL(region?: string): string { export function getLiveKitURL(region?: string | string[]): string {
let targetKey = 'NEXT_PUBLIC_LK_SERVER_URL'; let targetKey = 'LIVEKIT_URL';
if (region) { if (region && !Array.isArray(region)) {
targetKey = `NEXT_PUBLIC_LK_SERVER_URL${region}`.toUpperCase(); targetKey = `LIVEKIT_URL_${region}`.toUpperCase();
} }
const url = process.env[targetKey]; const url = process.env[targetKey];
if (!url) { if (!url) {

View file

@ -12,6 +12,5 @@ export interface SessionProps {
export interface TokenResult { export interface TokenResult {
identity: string; identity: string;
url: string;
accessToken: string; accessToken: string;
} }

View file

@ -2,7 +2,6 @@ import { NextApiRequest, NextApiResponse } from 'next';
import { AccessToken } from 'livekit-server-sdk'; import { AccessToken } from 'livekit-server-sdk';
import type { AccessTokenOptions, VideoGrant } from 'livekit-server-sdk'; import type { AccessTokenOptions, VideoGrant } from 'livekit-server-sdk';
import { getLiveKitURL } from '../../lib/clients';
import { TokenResult } from '../../lib/types'; import { TokenResult } from '../../lib/types';
const apiKey = process.env.LIVEKIT_API_KEY; const apiKey = process.env.LIVEKIT_API_KEY;
@ -19,7 +18,7 @@ const roomPattern = /\w{4}\-\w{4}/;
export default async function handleToken(req: NextApiRequest, res: NextApiResponse) { export default async function handleToken(req: NextApiRequest, res: NextApiResponse) {
try { try {
const { roomName, identity, name, metadata, region } = req.query; const { roomName, identity, name, metadata } = req.query;
if (typeof identity !== 'string' || typeof roomName !== 'string') { if (typeof identity !== 'string' || typeof roomName !== 'string') {
res.status(403).end(); res.status(403).end();
@ -32,9 +31,6 @@ export default async function handleToken(req: NextApiRequest, res: NextApiRespo
if (Array.isArray(metadata)) { if (Array.isArray(metadata)) {
throw Error('provide max one metadata string'); throw Error('provide max one metadata string');
} }
if (Array.isArray(region)) {
throw Error('provide max one region string');
}
// enforce room name to be xxxx-xxxx // enforce room name to be xxxx-xxxx
// this is simple & naive way to prevent user from guessing room names // this is simple & naive way to prevent user from guessing room names
@ -61,7 +57,6 @@ export default async function handleToken(req: NextApiRequest, res: NextApiRespo
const result: TokenResult = { const result: TokenResult = {
identity, identity,
accessToken: token, accessToken: token,
url: getLiveKitURL(region),
}; };
res.status(200).json(result); res.status(200).json(result);

17
pages/api/url.ts Normal file
View file

@ -0,0 +1,17 @@
import { NextApiRequest, NextApiResponse } from 'next';
import { getLiveKitURL } from '../../lib/server-utils';
export default async function handleServerUrl(req: NextApiRequest, res: NextApiResponse) {
try {
const { region } = req.query;
if (Array.isArray(region)) {
throw Error('provide max one region string');
}
const url = getLiveKitURL(region);
res.status(200).json({ url });
} catch (e) {
res.statusMessage = (e as Error).message;
res.status(500).end();
}
}

View file

@ -5,13 +5,15 @@ import {
useToken, useToken,
VideoConference, VideoConference,
} from '@livekit/components-react'; } from '@livekit/components-react';
import { RoomOptions } from 'livekit-client'; import { LogLevel, RoomOptions } from 'livekit-client';
import type { NextPage } from 'next'; import type { NextPage } from 'next';
import Head from 'next/head'; import Head from 'next/head';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { useMemo, useState } from 'react'; import { useMemo, useState } from 'react';
import { getLiveKitURL } from '../../lib/server-utils';
import { DebugMode } from '../../lib/Debug'; import { DebugMode } from '../../lib/Debug';
import { useServerUrl } from '../../lib/client-utils';
const Home: NextPage = () => { const Home: NextPage = () => {
const router = useRouter(); const router = useRouter();
@ -58,6 +60,7 @@ export default Home;
type ActiveRoomProps = { type ActiveRoomProps = {
userChoices: LocalUserChoices; userChoices: LocalUserChoices;
roomName: string; roomName: string;
region?: string;
onLeave?: () => void; onLeave?: () => void;
}; };
const ActiveRoom = ({ roomName, userChoices, onLeave }: ActiveRoomProps) => { const ActiveRoom = ({ roomName, userChoices, onLeave }: ActiveRoomProps) => {
@ -70,6 +73,11 @@ const ActiveRoom = ({ roomName, userChoices, onLeave }: ActiveRoomProps) => {
}, },
}); });
const router = useRouter();
const { region } = router.query;
const liveKitUrl = useServerUrl(region as string | undefined);
const roomOptions = useMemo((): RoomOptions => { const roomOptions = useMemo((): RoomOptions => {
return { return {
videoCaptureDefaults: { videoCaptureDefaults: {
@ -84,16 +92,20 @@ const ActiveRoom = ({ roomName, userChoices, onLeave }: ActiveRoomProps) => {
}, [userChoices]); }, [userChoices]);
return ( return (
<LiveKitRoom <>
token={token} {liveKitUrl && (
serverUrl={process.env.NEXT_PUBLIC_LK_SERVER_URL} <LiveKitRoom
options={roomOptions} token={token}
video={userChoices.videoEnabled} serverUrl={liveKitUrl}
audio={userChoices.audioEnabled} options={roomOptions}
onDisconnected={onLeave} video={userChoices.videoEnabled}
> audio={userChoices.audioEnabled}
<VideoConference /> onDisconnected={onLeave}
<DebugMode /> >
</LiveKitRoom> <VideoConference />
<DebugMode logLevel={LogLevel.info} />
</LiveKitRoom>
)}
</>
); );
}; };