Remote Config (v1)¶
API-метод Remote Config позволяет получить актуальный набор параметров для проекта, который определяется по токену доступа. Подробнее о создании токена читайте в руководстве по аутентификации.
Метод предназначен для динамического конфигурирования приложения без внесения изменений в исходный код.
| Метод | Endpoint |
|---|---|
| POST | /v1/configs |
Почему используется POST, а не GET?
Хотя текущая версия метода не требует тела запроса, использование POST является осознанным архитектурным решением для обеспечения обратной совместимости. В будущем это позволит передавать в теле запроса контекст пользователя (например, геолокацию, версию приложения) для таргетинга параметров или участия в A/B-тестах, не изменяя при этом эндпоинт.
Пример будущего тела запроса:
{
"conditions": {
"country": "DE",
"appVersion": "2.3.1"
},
"experiments": {
"checkout_redesign": "B"
}
}
Тело запроса¶
Тело запроса для данного вызова должно быть пустым.
Структура ответа¶
API возвращает плоский JSON-объект, где каждый ключ является строковым идентификатором параметра, а значение — его актуальным значением.
Тип каждого значения (String, Boolean, Number или JSON) определяется при создании параметра в панели управления. Подробнее: Инструкция по настройке параметров.
Возможные типы значений:
| Тип в панели управления | Пример значения в ответе |
|---|---|
String |
"Добро пожаловать!" |
Boolean |
true |
Number |
500 или 7.5 |
JSON |
"{\"default\":\"card\",\"methods\":[\"card\"]}" |
Особенность обработки типа JSON
Если параметр имеет тип JSON, его значение будет возвращено в виде экранированной строки, а не вложенного JSON-объекта. Вам потребуется дополнительный парсинг этой строки в вашем коде.
Примеры запроса¶
curl -X POST https://<DOMAIN>/v1/configs \
-H "Authorization: Bearer <ENCODED_TOKEN>" \
-H "Content-Type: application/json"
import requests
url = "https://<DOMAIN>/v1/configs"
headers = {
"Authorization": "Bearer <ENCODED_TOKEN>",
"Content-Type": "application/json"
}
response = requests.post(url, headers=headers)
response.raise_for_status()
config = response.json()
const url = "https://<DOMAIN>/v1/configs";
const options = {
method: "POST",
headers: {
"Authorization": "Bearer <ENCODED_TOKEN>",
"Content-Type": "application/json"
}
};
fetch(url, options)
.then(response => {
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
return response.json();
})
.then(config => console.log(config))
.catch(error => console.error('Error fetching config:', error));
using System.Net.Http.Headers;
using System.Text.Json;
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://<DOMAIN>/v1/configs");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "<ENCODED_TOKEN>");
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
var config = await response.Content.ReadFromJsonAsync<Dictionary<string, JsonElement>>();
package main
import (
"encoding/json"
"net/http"
)
func main() {
client := &http.Client{}
req, _ := http.NewRequest("POST", "https://<DOMAIN>/v1/configs", nil)
req.Header.Add("Authorization", "Bearer <ENCODED_TOKEN>")
res, err := client.Do(req)
if err != nil { /* ... обработка ошибки ... */ }
defer res.Body.Close()
var config map[string]interface{}
json.NewDecoder(res.Body).Decode(&config)
}
import okhttp3.*;
import org.json.JSONObject;
import java.io.IOException;
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://<DOMAIN>/v1/configs")
.post(RequestBody.create(new byte[0]))
.addHeader("Authorization", "Bearer <ENCODED_TOKEN>")
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
JSONObject config = new JSONObject(response.body().string());
}
В параметре <DOMAIN> указывается адрес вашего сервера. В зависимости от типа вашей установки, это может быть:
- On-premises / Private Cloud: используйте ваш корпоративный домен.
- SaaS: версия в разработке (домен будет предоставлен после выпуска).
Примеры ответа¶
{
"isNewFeatureEnabled": true,
"maxUsers": 500,
"welcomeText": "Добро пожаловать!",
"paymentOptions": "{\"methods\":[\"card\",\"apple_pay\",\"google_pay\"],\"default\":\"card\"}"
}
{}
Примеры обработки ответа¶
Лучшая практика: Отказоустойчивый доступ
Мы настоятельно рекомендуем всегда указывать локальное значение по умолчанию при получении параметра из конфигурации. Это делает ваше приложение устойчивым к непредвиденным ситуациям, таким как удаление параметра в панели администратора.
Все приведенные ниже примеры следуют этому принципу.
Boolean¶
is_feature_enabled: bool = config.get('isNewFeatureEnabled', False)
const isFeatureEnabled = config.isNewFeatureEnabled || false;
bool isFeatureEnabled = config.TryGetValue("isNewFeatureEnabled", out var el) && el.ValueKind == JsonValueKind.True;
isFeatureEnabled, _ := config["isNewFeatureEnabled"].(bool)
boolean isFeatureEnabled = config.optBoolean("isNewFeatureEnabled", false);
Number¶
max_users: int = config.get('maxUsers', 0)
const maxUsers = config.maxUsers || 0;
int maxUsers = config.TryGetValue("maxUsers", out var el) ? el.GetInt32() : 0;
maxUsers, _ := config["maxUsers"].(float64)
int maxUsers = config.optInt("maxUsers", 0);
String¶
welcome_text: str = config.get('welcomeText', '')
const welcomeText = config.welcomeText || '';
string welcomeText = config.TryGetValue("welcomeText", out var el) ? el.GetString() : "";
welcomeText, _ := config["welcomeText"].(string)
String welcomeText = config.optString("welcomeText", "");
JSON (требует двойного парсинга)¶
import json
payment_options_str = config.get('paymentOptions', '{}')
payment_options = json.loads(payment_options_str)
methods = payment_options.get('methods', [])
default_method = payment_options.get('default', '')
const paymentOptionsStr = config.paymentOptions || '{}';
const paymentOptions = JSON.parse(paymentOptionsStr);
const methods = paymentOptions.methods || [];
const defaultMethod = paymentOptions.default || '';
using System.Text.Json;
using System.Collections.Generic;
using System.Linq;
string paymentOptionsStr = config.TryGetValue("paymentOptions", out var el) ? el.GetString() : "{}";
var paymentOptions = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(paymentOptionsStr);
List<string> methods = new List<string>();
if (paymentOptions.TryGetValue("methods", out var methodsEl) && methodsEl.ValueKind == JsonValueKind.Array)
{
methods = methodsEl.EnumerateArray().Select(m => m.GetString()).ToList();
}
string defaultMethod = "";
if (paymentOptions.TryGetValue("default", out var defaultEl) && defaultEl.ValueKind == JsonValueKind.String)
{
defaultMethod = defaultEl.GetString();
}
import "encoding/json"
var paymentOptions map[string]interface{}
if paymentOptionsStr, ok := config["paymentOptions"].(string); ok {
json.Unmarshal([]byte(paymentOptionsStr), &paymentOptions)
}
var methods []string
if methodsInterface, ok := paymentOptions["methods"].([]interface{}); ok {
for _, m := range methodsInterface {
if methodStr, ok := m.(string); ok {
methods = append(methods, methodStr)
}
}
}
defaultMethod, _ := paymentOptions["default"].(string)
import org.json.JSONObject;
import org.json.JSONArray;
import java.util.ArrayList;
import java.util.List;
String paymentOptionsStr = config.optString("paymentOptions", "{}");
JSONObject paymentOptions = new JSONObject(paymentOptionsStr);
JSONArray methodsArray = paymentOptions.optJSONArray("methods");
List<String> methods = new ArrayList<>();
if (methodsArray != null) {
for (int i = 0; i < methodsArray.length(); i++) {
methods.add(methodsArray.getString(i));
}
}
String defaultMethod = paymentOptions.optString("default", "");
См. также¶
- Создание параметра - пошаговая инструкция по созданию параметров через интерфейс.
- Управление параметрами - руководство по управлению параметрами в веб-интерфейсе.