Kanal API Endpunkt
Kanäle sind ein zentraler Mechanismus zum Verwalten von App-Updates in Capgo. Im selbstgehosteten Modus müssen Sie Kanalendpunkte implementieren, um Gerätezuweisungen, Kanalabfragen und Kanalverwaltungsvorgänge zu verarbeiten.
Kanäle verstehen
Section titled “Kanäle verstehen”Mit Kanälen können Sie:
- Update-Verteilung steuern: Weisen Sie verschiedenen Benutzergruppen verschiedene App-Versionen zu
- A/B-Tests: Testen Sie neue Funktionen mit bestimmten Benutzersegmenten
- Stufenweise Einführung: Stellen Sie Updates schrittweise bereit, um das Risiko zu minimieren
- Umgebungstrennung: Separate Entwicklungs-, Staging- und Produktionsaktualisierungen
Konfiguration
Section titled “Konfiguration”Konfigurieren Sie die Kanalendpunkt-URL in Ihrem capacitor.config.json:
{ "plugins": { "CapacitorUpdater": { "channelUrl": "https://myserver.com/api/channel_self" } }}Kanaloperationen
Section titled “Kanaloperationen”Das Plugin führt verschiedene Kanaloperationen aus, die Ihr Endpunkt verarbeiten muss:
1. Kompatible Kanäle auflisten (GET-Anfrage)
Section titled “1. Kompatible Kanäle auflisten (GET-Anfrage)”Wenn das Plugin listChannels() aufruft, sendet es eine GET-Anfrage, um alle Kanäle abzurufen, die mit dem Gerät kompatibel sind. Dadurch werden Kanäle zurückgegeben, die zur Geräteumgebung (Entwickler/Produkt, Emulator/reales Gerät) passen und entweder öffentlichen Zugriff oder Selbstzuweisung ermöglichen.
Anforderungsformat
Section titled “Anforderungsformat”// GET /api/channel_self// Headers:{ "Content-Type": "application/json"}
// Query parameters:interface ListChannelsRequest { app_id: string platform: "ios" | "android" | "electron" is_emulator: boolean is_prod: boolean key_id?: string}Antwortformat
Section titled “Antwortformat”[ { "id": 1, "name": "production", "public": true, "allow_self_set": false }, { "id": 2, "name": "beta", "public": false, "allow_self_set": true }]Kanaltypen verstehen
Section titled “Kanaltypen verstehen”Die Antwort enthält zwei wichtige Flags für jeden Kanal:
-
public: true: Dies ist ein Standardkanal. Geräte können sich mitsetChannel()nicht selbst zuweisen. Wenn ein Gerät stattdessen seine Kanalzuweisung entfernt (mithilfe vonunsetChannel()), erhält es automatisch Updates von diesem öffentlichen Kanal, wenn er den Bedingungen des Geräts entspricht. -
allow_self_set: true: Dies ist ein selbst zuweisbarer Kanal. MitsetChannel()können sich Geräte explizit diesem Kanal zuordnen. Dies ist nützlich für Betatests, A/B-Tests oder um Benutzern die Möglichkeit zu geben, sich für bestimmte Update-Tracks zu entscheiden.
2. Kanal abrufen (PUT-Anfrage)
Section titled “2. Kanal abrufen (PUT-Anfrage)”Wenn das Plugin getChannel() aufruft, sendet es eine PUT-Anfrage, um die aktuelle Kanalzuweisung des Geräts abzurufen.
Anforderungsformat
Section titled “Anforderungsformat”// PUT /api/channel_self// Headers:{ "Content-Type": "application/json"}
// Body:interface GetChannelRequest { device_id: string app_id: string platform: "ios" | "android" | "electron" plugin_version: string version_build: string version_code: string version_name: string is_emulator: boolean is_prod: boolean defaultChannel?: string channel?: string // For newer plugin versions, contains local channel override}Antwortformat
Section titled “Antwortformat”{ "status": "ok", "channel": "production", "allowSet": true, "message": "", "error": ""}3. Kanal einstellen (POST-Anfrage)
Section titled “3. Kanal einstellen (POST-Anfrage)”Wenn das Plugin setChannel() aufruft, sendet es eine POST-Anfrage, um das Gerät einem bestimmten Kanal zuzuweisen.
Anforderungsformat
Section titled “Anforderungsformat”// POST /api/channel_selfinterface SetChannelRequest { device_id: string app_id: string channel: string platform: "ios" | "android" | "electron" plugin_version: string version_build: string version_code: string version_name: string is_emulator: boolean is_prod: boolean}Antwortformat
Section titled “Antwortformat”{ "status": "ok", "message": "Device assigned to channel successfully", "error": ""}Fehlerfälle
Section titled “Fehlerfälle”Wenn ein Gerät versucht, sich einem öffentlichen Kanal (einem mit public: true) zuzuweisen, sollte Ihr Endpunkt einen Fehler zurückgeben:
{ "status": "error", "error": "public_channel_self_set_not_allowed", "message": "This channel is public and does not allow device self-assignment. Unset the channel and the device will automatically use the public channel."}Wenn ein Gerät versucht, sich selbst einem Kanal zuzuweisen, der keine Selbstzuweisung zulässt:
{ "status": "error", "error": "channel_self_set_not_allowed", "message": "This channel does not allow devices to self associate"}4. Kanal deaktivieren (DELETE-Anfrage)
Section titled “4. Kanal deaktivieren (DELETE-Anfrage)”Wenn das Plugin unsetChannel() aufruft, sendet es eine DELETE-Anfrage, um die Kanalzuweisung des Geräts zu entfernen.
Anforderungsformat
Section titled “Anforderungsformat”// DELETE /api/channel_selfinterface UnsetChannelRequest { device_id: string app_id: string platform: "ios" | "android" | "electron" plugin_version: string version_build: string version_code: string version_name: string}Implementierungsbeispiel
Section titled “Implementierungsbeispiel”Hier ist ein JavaScript-Beispiel für die Implementierung des Kanalendpunkts:
interface ChannelRequest { device_id: string app_id: string channel?: string platform: "ios" | "android" | "electron" plugin_version: string version_build: string version_code: string version_name: string}
interface ChannelResponse { status: "ok" | "error" channel?: string allowSet?: boolean message?: string error?: string}
export const handler = async (event) => { const method = event.httpMethod || event.method const body = JSON.parse(event.body || '{}') as ChannelRequest
const { device_id, app_id, channel, platform } = body
try { switch (method) { case 'GET': return await getDeviceChannel(device_id, app_id)
case 'POST': return await setDeviceChannel(device_id, app_id, channel!, platform)
case 'DELETE': return await unsetDeviceChannel(device_id, app_id)
default: return { status: "error", error: "Method not allowed" } } } catch (error) { return { status: "error", error: error.message } }}
async function getDeviceChannel(deviceId: string, appId: string): Promise<ChannelResponse> { // Query your database for device channel assignment const assignment = await database.getDeviceChannel(deviceId, appId)
if (assignment) { return { status: "ok", channel: assignment.channel, allowSet: assignment.allowSelfAssign } }
// Return default channel if no assignment found return { status: "ok", channel: "production", // Your default channel allowSet: true }}
async function setDeviceChannel( deviceId: string, appId: string, channel: string, platform: string): Promise<ChannelResponse> { // Validate channel exists and allows self-assignment const channelConfig = await database.getChannelConfig(channel, appId)
if (!channelConfig) { return { status: "error", error: "Channel not found" } }
if (!channelConfig.allowDeviceSelfSet) { return { status: "error", error: "Channel does not allow self-assignment" } }
// Check platform restrictions if (platform === "ios" && !channelConfig.ios) { return { status: "error", error: "Channel not available for iOS" } }
if (platform === "android" && !channelConfig.android) { return { status: "error", error: "Channel not available for Android" } }
if (platform === "electron" && !channelConfig.electron) { return { status: "error", error: "Channel not available for Electron" } }
// Save the assignment await database.setDeviceChannel(deviceId, appId, channel)
return { status: "ok", message: "Device assigned to channel successfully" }}
async function unsetDeviceChannel(deviceId: string, appId: string): Promise<ChannelResponse> { // Remove device channel assignment await database.removeDeviceChannel(deviceId, appId)
return { status: "ok", message: "Device channel assignment removed" }}Kanalkonfiguration
Section titled “Kanalkonfiguration”Ihr Kanalsystem sollte diese Konfigurationsoptionen unterstützen:
interface ChannelConfig { name: string appId: string
// Platform targeting ios: boolean // Allow updates to iOS devices android: boolean // Allow updates to Android devices electron: boolean // Allow updates to Electron apps
// Device type restrictions allow_emulator: boolean // Allow updates on emulator/simulator devices allow_device: boolean // Allow updates on real/physical devices
// Build type restrictions allow_dev: boolean // Allow updates on development builds (is_prod=false) allow_prod: boolean // Allow updates on production builds (is_prod=true)
// Channel assignment public: boolean // Default channel - devices fall back to this when no override allowDeviceSelfSet: boolean // Allow devices to self-assign via setChannel()
// Update policies disableAutoUpdate: "major" | "minor" | "version_number" | "none" disableAutoUpdateUnderNative: boolean}GerätefilterlogikBeim Auflisten kompatibler Kanäle (GET-Anfrage) sollten Sie Kanäle anhand dieser Bedingungen filtern:
Section titled “GerätefilterlogikBeim Auflisten kompatibler Kanäle (GET-Anfrage) sollten Sie Kanäle anhand dieser Bedingungen filtern:”- Plattformprüfung: Der Kanal muss die Plattform des Geräts zulassen (
ios,androidoderelectron) - Gerätetypprüfung:
- Wenn
is_emulator=true: Kanal mussallow_emulator=truehaben - Wenn
is_emulator=false: Kanal mussallow_device=truehaben
- Wenn
- Überprüfung des Build-Typs:
- Wenn
is_prod=true: Kanal mussallow_prod=truehaben - Wenn
is_prod=false: Kanal mussallow_dev=truehaben
- Wenn
- Sichtbarkeitsprüfung: Der Kanal muss entweder
public=trueODERallow_device_self_set=truesein
// Example filtering logicfunction getCompatibleChannels( platform: 'ios' | 'android' | 'electron', isEmulator: boolean, isProd: boolean, channels: ChannelConfig[]): ChannelConfig[] { return channels.filter(channel => { // Platform check if (!channel[platform]) return false
// Device type check if (isEmulator && !channel.allow_emulator) return false if (!isEmulator && !channel.allow_device) return false
// Build type check if (isProd && !channel.allow_prod) return false if (!isProd && !channel.allow_dev) return false
// Must be accessible (public or self-assignable) if (!channel.public && !channel.allowDeviceSelfSet) return false
return true })}Beispiel für ein Datenbankschema
Section titled “Beispiel für ein Datenbankschema”Sie müssen Kanalkonfigurationen und Gerätezuweisungen speichern:
-- Channels tableCREATE TABLE channels ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, app_id VARCHAR(255) NOT NULL,
-- Platform targeting ios BOOLEAN DEFAULT true, android BOOLEAN DEFAULT true, electron BOOLEAN DEFAULT true,
-- Device type restrictions allow_emulator BOOLEAN DEFAULT true, -- Allow emulator/simulator devices allow_device BOOLEAN DEFAULT true, -- Allow real/physical devices
-- Build type restrictions allow_dev BOOLEAN DEFAULT true, -- Allow development builds allow_prod BOOLEAN DEFAULT true, -- Allow production builds
-- Channel assignment public BOOLEAN DEFAULT false, -- Default channel (fallback) allow_device_self_set BOOLEAN DEFAULT false, -- Allow self-assignment
-- Update policies disable_auto_update VARCHAR(50) DEFAULT 'none', disable_auto_update_under_native BOOLEAN DEFAULT false,
created_at TIMESTAMP DEFAULT NOW(), UNIQUE(name, app_id));
-- Device channel assignments tableCREATE TABLE device_channels ( id SERIAL PRIMARY KEY, device_id VARCHAR(255) NOT NULL, app_id VARCHAR(255) NOT NULL, channel_name VARCHAR(255) NOT NULL, assigned_at TIMESTAMP DEFAULT NOW(), UNIQUE(device_id, app_id));Fehlerbehandlung
Section titled “Fehlerbehandlung”Behandeln Sie häufige Fehlerszenarien:
// Channel not found{ "status": "error", "error": "Channel 'beta' not found"}
// Self-assignment not allowed{ "status": "error", "error": "Channel does not allow device self-assignment"}
// Platform not supported{ "status": "error", "error": "Channel not available for this platform"}
// Invalid request{ "status": "error", "error": "Missing required field: device_id"}Bewährte Methoden
Section titled “Bewährte Methoden”- Sicherheit: Überprüfen Sie alle Kanalzuweisungen anhand Ihrer Geschäftsregeln
- Protokollierung: Protokollieren Sie alle Kanalvorgänge zur Überwachung und zum Debuggen
- Leistung: Kanalkonfigurationen zwischenspeichern, um Datenbankabfragen zu reduzieren
- Validierung: Überprüfen Sie die Authentizität von Geräte-ID und App-ID
- Ratenbegrenzung: Implementieren Sie eine Ratenbegrenzung, um Missbrauch zu verhindern
Integration mit Updates
Section titled “Integration mit Updates”Kanalzuweisungen funktionieren mit Ihrem Update API Endpoint. Wenn ein Gerät ein Update anfordert, überprüfen Sie seine Kanalzuweisung, um zu bestimmen, welche Version bereitgestellt werden soll:
async function getUpdateForDevice(deviceId: string, appId: string) { // Get device's channel assignment const channelAssignment = await getDeviceChannel(deviceId, appId) const channel = channelAssignment.channel || 'production'
// Get the version assigned to this channel const channelVersion = await getChannelVersion(channel, appId)
return { version: channelVersion.version, url: channelVersion.url, checksum: channelVersion.checksum }}Dadurch entsteht ein vollständiges, selbst gehostetes Kanalverwaltungssystem, das Ihnen die volle Kontrolle darüber gibt, wie Updates an Ihre Benutzer verteilt werden.