1import { parse } from 'url'; 2 3import { ServerRequest } from './server.types'; 4import { CommandError } from '../../../utils/errors'; 5 6const debug = require('debug')( 7 'expo:start:server:middleware:resolvePlatform' 8) as typeof console.log; 9 10/** Supported platforms */ 11export type RuntimePlatform = 'ios' | 'android'; 12 13/** 14 * Extract the runtime platform from the server request. 15 * 1. Query param `platform`: `?platform=ios` 16 * 2. Header `expo-platform`: `'expo-platform': ios` 17 * 3. Legacy header `exponent-platform`: `'exponent-platform': ios` 18 * 19 * Returns first item in the case of an array. 20 */ 21export function parsePlatformHeader(req: ServerRequest): string | null { 22 const url = parse(req.url!, /* parseQueryString */ true); 23 const platform = 24 url.query?.platform || req.headers['expo-platform'] || req.headers['exponent-platform']; 25 return (Array.isArray(platform) ? platform[0] : platform) ?? null; 26} 27 28/** Guess the platform from the user-agent header. */ 29export function resolvePlatformFromUserAgentHeader(req: ServerRequest): string | null { 30 let platform = null; 31 const userAgent = req.headers['user-agent']; 32 if (userAgent?.match(/Android/i)) { 33 platform = 'android'; 34 } 35 if (userAgent?.match(/iPhone|iPad/i)) { 36 platform = 'ios'; 37 } 38 debug(`Resolved platform ${platform} from user-agent header: ${userAgent}`); 39 return platform; 40} 41 42/** Assert if the runtime platform is not included. */ 43export function assertMissingRuntimePlatform(platform?: any): asserts platform { 44 if (!platform) { 45 throw new CommandError( 46 'PLATFORM_HEADER', 47 `Must specify "expo-platform" header or "platform" query parameter` 48 ); 49 } 50} 51 52/** Assert if the runtime platform is not correct. */ 53export function assertRuntimePlatform(platform: string): asserts platform is RuntimePlatform { 54 const stringifiedPlatform = String(platform); 55 if (!['android', 'ios', 'web'].includes(stringifiedPlatform)) { 56 throw new CommandError( 57 'PLATFORM_HEADER', 58 `platform must be "android", "ios", or "web". Received: "${platform}"` 59 ); 60 } 61} 62