@MaximNosko

Почему возникает TypeError: Failed to fetch при запросе к серверу из VK Mini App только из приложения на Android?

На сервере запущен Express-сервер, у него разрешены кроссдоменные запросы, настроен сертификат, и у браузеров нет проблем с тем, чтобы получить оттуда статическую страницу, или сделать на него запрос к API, в том числе, если приложение запущено в браузере на сайте ВК (статика подгружается из ВК, поэтому запросы кроссдоменные).

const app = express();
app.use(cors({origin: "*",}));
// ...
t = https.createServer({key:pk,cert:sf},app);
t.listen(443,()=>{console.log("start")});


Более того, если открыть приложение в официальном клиенте на iOS, то запросы к серверу также проходят, и всё работает.

И только если приложение открыто в официальном клиенте на Android, запрос не просто не успешно завершается, а он даже, возможно, не начинается, выкидывая исключение TypeError: Failed to fetch.

Я добавил в приложение консоль Eruda, чтобы посмотреть на код запроса или заголовки, но даже их нет, в консоли (во вкладке работы с сетью) просто написано pending... и статус unknown.

При этом, точно такой же код при обращении к сторонним доступным извне API, типа курсов валют (используя GET, но GET также не работает в случае моего сервера), работает прямо из приложения:

const requestOptions = {
    method: 'POST',
    body: JSON.stringify(jsonData),
    headers:{'content-type': 'application/json'},
};
try
{
    let zapros = await fetch(myURL, requestOptions);
// ...


Проблема возникла точно не из-за кроссдоменности, так как изначально я хостил и API, и статику, но статику получилось выгрузить в ВК через их технологию Deploy, а до этого приложение не получало даже статики и вечно загружалось, в то время как браузеры на всех моих устройствах не видели проблем с тем, чтобы получить от моего сервера как статику, так и ответ на POST-запрос.

Так как код выполняется всеми браузерами, включая даже Edge, нельзя назвать клиентскую часть сильно проблемной, хоть и что-то в ней, возможно, не так. Более того, ещё до запуска клиентской части, когда я пытался хостить статику, приложение само делало к статике GETы, которые не "выходили" (скорее всего) из приложения.

Помимо этого, я пробовал запускать Restify на сервере, чтобы хоть какой-нибудь маленький бесполезный запрос всё же прошёл, но и в этом случае браузеры получали ответ, а код внутри приложения ВК - нет.

В случае же, если использовать Ngrok или VK-Tunnel, всё работает, но это совсем не то, что нужно, учитывая, что адрес не будет постоянным.

Единственное, что примечательно в моей серверной части - сервер слушает только 443 порт, без 80, а также то, что домену, как и сертификату всего около недели, и, возможно, к ним из-за этого мало доверия. Но сертификат, хоть и новый, настоящий (не самодельный), куплен в RU-CENTER, назывался там "GlobalSign DomainSSL", один из тех, что доступен для физлиц, и браузеры на всех устройствах не жалуются, пишут, что всё безопасно.

Не нашёл в интернете подобных ситуаций, так как на мой взгляд сама ситуация не вполне адекватна, учитывая то, что WebView в приложении ВК должно вести себя с сетью также, как и ведущие браузеры на том же устройстве.

Надеюсь, можно как-то изменить код на серверной или на клиентской стороне, чтобы запросы проходили при открытии приложения внутри приложения ВК на Android.
  • Вопрос задан
  • 2948 просмотров
Решения вопроса 1
@MaximNosko Автор вопроса
Нашёл решение:
Проблема оказалась в том, что был указан только сертификат и закрытый ключ, а корневой и промежуточный сертификаты не были указаны в настройках Express-сервера:
let pk = fs.readFileSync("key.key");
let sf = fs.readFileSync("сert.crt");
// Добавлено:
let root_c = fs.readFileSync("root.crt"); // Корневой сертификат
let prom = fs.readFileSync("prom.crt"); // Промежуточный сертификат

t = https.createServer({key:pk,cert:sf,ca:[root_c,prom]},app);


То есть, браузерам было достаточно и двух "частей" сертификата, а вот приложению - нет
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы