// Automatic FlutterFlow imports import '/backend/schema/structs/index.dart'; import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; import 'index.dart'; // Imports other custom actions import '/flutter_flow/custom_functions.dart'; // Imports custom functions import 'package:flutter/material.dart'; // Begin custom action code // DO NOT REMOVE OR MODIFY THE CODE ABOVE! import 'dart:async'; import 'dart:convert'; import 'package:http/http.dart' as http; Future drupalRequest( String method, String url, String sessionName, String sessionId, String token, String body, ) async { try { final ingevoerdeUrl = url.trim(); final apiBase = FFAppState().apiBaseUrl.trim().isEmpty ? 'https://uitgaanskrant.com' : FFAppState().apiBaseUrl.trim(); url = (ingevoerdeUrl.startsWith('http://') || ingevoerdeUrl.startsWith('https://')) ? ingevoerdeUrl : apiBase + (ingevoerdeUrl.startsWith('/') ? ingevoerdeUrl : '/$ingevoerdeUrl'); //-------------------------------------------------- // Headers //-------------------------------------------------- final headers = { 'Accept': 'application/json', 'Content-Type': 'application/json', }; if (sessionName.trim().isNotEmpty && sessionId.trim().isNotEmpty) { headers['Cookie'] = '$sessionName=$sessionId'; } if (token.trim().isNotEmpty) { headers['X-CSRF-Token'] = token; } //-------------------------------------------------- // DEBUG //-------------------------------------------------- print('========================================'); print('DRUPAL REQUEST'); print('Method : $method'); print('URL : $url'); print('Headers'); headers.forEach((k, v) => print('$k: $v')); if (body.isNotEmpty) { print('Body'); print(body); } print('========================================'); //-------------------------------------------------- // Request //-------------------------------------------------- http.Response response; switch (method.toUpperCase()) { case 'POST': response = await http .post( Uri.parse(url), headers: headers, body: body, ) .timeout(const Duration(seconds: 30)); break; case 'PUT': response = await http .put( Uri.parse(url), headers: headers, body: body, ) .timeout(const Duration(seconds: 30)); break; case 'DELETE': response = await http .delete( Uri.parse(url), headers: headers, body: body, ) .timeout(const Duration(seconds: 30)); break; default: response = await http .get( Uri.parse(url), headers: headers, ) .timeout(const Duration(seconds: 30)); } //-------------------------------------------------- // DEBUG RESPONSE //-------------------------------------------------- print('========================================'); print('STATUS : ${response.statusCode}'); print('RESPONSE HEADERS'); response.headers.forEach((k, v) => print('$k: $v')); print('BODY'); print(response.body); print('========================================'); //-------------------------------------------------- // JSON of tekst //-------------------------------------------------- dynamic data; try { data = jsonDecode(response.body); } catch (_) { data = response.body; } if (response.statusCode >= 200 && response.statusCode < 300) { return data; } //-------------------------------------------------- // Sessie verlopen? (toegevoegd 2026-09-20, taak C) //-------------------------------------------------- // Alleen relevant als we zélf een cookie meestuurden: zonder cookie is een // 403 gewoon "dit endpoint vereist inloggen", niet "je sessie is weg". // // Drupal Services antwoordt bij een weggevallen sessie met 401, of met 403 // plus het woord "anonymous" ("Toegang geweigerd voor gebruiker anonymous"). // Een 403 zónder dat woord is een rechtenkwestie -- dan mag de gebruiker // niet uitgelogd worden. if (headers.containsKey('Cookie') && (response.statusCode == 401 || (response.statusCode == 403 && response.body.toLowerCase().contains('anonymous')))) { print('SESSIE VERLOPEN -> lokale sessie wissen'); // Exact dezelfde velden als de uitlogknop op Favorieten, zodat de app in // dezelfde uitgelogde staat komt. delete*() wist secure storage, de // toewijzing eronder de waarde in het geheugen. FFAppState().deleteUserSessionid(); FFAppState().deleteUserSessionname(); FFAppState().deleteUserToken(); FFAppState().deleteUserName(); FFAppState().deleteUserMail(); FFAppState().deleteUserUid(); // update() en niet de losse setters: alléén update() roept // notifyListeners() aan, en daar hangt VerbindingsBanner aan. FFAppState().update(() { FFAppState().userSessionid = ''; FFAppState().userSessionname = ''; FFAppState().userToken = ''; FFAppState().userName = ''; FFAppState().userMail = ''; FFAppState().userUid = 0; FFAppState().sessieVerlopen = true; }); } // De returnvorm blijft bewust een lege lijst: alle aanroepers doen blind // .toList() op het resultaat, dus een Map laat ze crashen. return []; } on TimeoutException { return []; } catch (e, stack) { print(e); print(stack); return []; } } // Set your action name, define your arguments and return parameter, // and then add the boilerplate code using the `` button on the right!