Access confluence page content using REST API in Flutter using Dart

Hello all, I am new to web development and I am currently facing some issues regarding access to the content of my confluence page using REST API calls in Flutter. Whenever I try to make the call, I get back the error ‘XMLHTTPRequesterror’ and when I inspect my console it tells me that there is a CORS rule not permitting the access. So I wish to know more and how I can proceed. Below I provide my code which works in Postman

and the error message.

class ContainerTitleApi extends StatefulWidget {
  @override
  _ContainerTitleApiState createState() => _ContainerTitleApiState();
}

class _ContainerTitleApiState extends State<ContainerTitleApi> {
  @override
  Widget build(BuildContext context) {
    return  Center(
            child: FutureBuilder<Post>(
            future: fetchPost(),
            builder: (context, snapshot) {
            if (snapshot.hasData) {
             return Text("${snapshot.data.title}");
            } else if (snapshot.hasError) {
              return Text("${snapshot.error}");
            }
            // By default, show a loading spinner.
            return CircularProgressIndicator();
          },
          ),
    );
  }
}


class Post {
  final String title;

  Post({this.title,});

  factory Post.fromJson(Map<String, dynamic> json) {
    return Post(
      title: json['title'],
    );
  }
}

Future<Post> fetchPost() async {
  var headers = {
    'Authorization': 'Basic *********'
  };
  var request = http.Request('GET', Uri.parse('http://proceedit.atlassian.net/wiki/rest/api/content/2413035961/child/page?expand=body.view.value'));

  request.headers.addAll(headers);

  http.StreamedResponse response = await request.send();

  if (response.statusCode == 200) {
    return Post.fromJson(json.decode(response.stream.toString()));
  }
  else {
    throw Exception(response.reasonPhrase);
  }

Are you creating a Connect app?

In that case, please see these instructions:
https://developer.atlassian.com/cloud/confluence/jsapi/request/
https://developer.atlassian.com/cloud/confluence/about-the-connect-javascript-api/

@leticiahamvegam welcome to the Atlassian developer community.

Regardless of the unique Flutter and Dart approach (at least from what I’ve seen here), you are probably just hitting plain old CORS policy, tripping the XSRF check. See XSRF check failed when calling Cloud APIs as a support FAQ. In short summary, you’ll have to pass X-Atlassian-Token: no-check as an HTTP header. But you should read the relevant docs because of the potential of opening a security hole on your Confluence instance.

Thank you for the reply. But I am trying to make a normal REST API call but CORS is not accepting

Thank you for the reply. I have tried applying the suggested solution in the resource but unfortunately I still get the same error.

According to your screenshot. this is because you are running Flutter Web. You can use a CORS proxy if you absolute want to call the JIRA API from the browser. Or you can build a small API running on you preferred cloud provider and call you API from Flutter.

1 Like

@leticiahamvegam Try to run your application using flutter run -d chrome --web-renderer html . By default, Flutter renders as CanvasKit and it won’t allow you to access the content from another server (CORS policy).

Hello @leticiahamvegam. Finally you were able to solve your problem ?. I have the same problem.

Hi.

I’m having the same issue with dart. I have added the header that @ibuchanan mentioned. But nothing. Any ideas?

import 'dart:convert';
import 'package:dio/dio.dart';

main() async {

  const jiraApiUrl = 'https://proyectosgmb.atlassian.net/rest/api/2/issue';
  const projectKey = 'ACR';
  const userJira = 'lbowen@robotilsa.com';
  const tokenJira = 'ATATT...9A';


  Map<String, dynamic> requestData = {
      'fields': {
        'project': {'key': projectKey},
        'summary': 'HOLA',
        'description': "description",
        'issuetype': {'name': 'Task'}
      }
    };

    String requestBody = jsonEncode(requestData);
    
  try {

      final response = await Dio().post(
jiraApiUrl,
data: requestBody,
        options: Options(
          method: 'POST',
          headers: <String, String>{
            'X-Atlassian-Token': 'no-check', 
            'Content-Type': 'application/json',
             'Accept': 'application/json', 
              'Access-Control-Allow-Methods': 'OPTIONS, GET, PUT, DELETE',
              'Access-Control-Allow-Credentials': 'true',
              'Access-Control-Expose-Headers': 'Origin, Authorization, Content-Type',          
            'Authorization':
                'Basic ${base64Encode(utf8.encode('$userJira:$tokenJira'))}',
          
          }
        )
      );

      if (response.statusCode != 201) {
        print("GOOD");
      }
      return response.statusCode == 201;
    } catch (e) {
      print("ERROR JIRA: $e");
      return false;
    }
}

The strangest thing is that with postman is working and also with python script:

import requests
import json
from requests.auth import HTTPBasicAuth


def create_jira_task(titulo, description):
    jira_api_url = 'https://proyectosgmb.atlassian.net/rest/api/2/issue'
    project_key = 'ACR'
    user_jira = 'lbowen@robotilsa.com'
    token_jira = 'ATATT...9A'

    request_data = {
        'fields': {
            'project': {'key': project_key},
            'summary': titulo,
            'description': description,
            'issuetype': {'name': 'Task'}
        }
    }

    request_body = json.dumps(request_data)

    headers = {
        'Content-Type': 'application/json',
        'Authorization': f'Basic {user_jira}:{token_jira}'
    }

    try:
        # Realizar la solicitud POST a la API de Jira
        response = requests.post(
            jira_api_url,
            headers=headers,
            data=request_body.encode('utf-8'),
            auth=HTTPBasicAuth(user_jira, token_jira)
        )

        print("Status Code:", response.status_code)
        print("Body response", response.content)

        if response.status_code != 201:
            print("Error al crear la tarea en Jira")
            return False

        return True
    except Exception as e:
        print("Error Jira:", e)
        return False


titulo = "Título de la tarea"
descripcion = "Descripción de la tarea"
create_jira_task(titulo, descripcion)

Por consola me saca:

ERROR JIRA: DioException [connection error]: The connection errored: The XMLHttpRequest onError callback was called. This typically indicates an error on the network layer.