'SOAP Request in Flutter/Dart

I need to make a SOAP request to a .NET Webservice (WSDL) with Flutter.

This webservice has an basic auth (user, password) and some services with pre-defined envelopes.

So I tried to create a SOAP envelope:

String requestBody = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:tot=\"http://www.totvs.com/\">   <soapenv:Header/>   <soapenv:Body>      <tot:RealizarConsultaSQL>         <!--Optional:-->         <tot:codSentenca>ETHOS.TESTE</tot:codSentenca>         <!--Optional:-->         <tot:codColigada>0</tot:codColigada>         <!--Optional:-->         <tot:codSistema>F</tot:codSistema>         <!--Optional:-->         <tot:parameters></tot:parameters>      </tot:RealizarConsultaSQL>   </soapenv:Body></soapenv:Envelope>";

This envelope is valid. The second step was to make a http connection:

http.Response response = await http.post(
  request,
  headers: {
    "Accept-Encoding": "gzip,deflate",
    "Content-Length": utf8.encode(requestBody).length.toString(),
    "Content-Type": "text/xmlc",
    "SOAPAction": "http://www.totvs.com/IwsConsultaSQL/RealizarConsultaSQL",
    "Authorization": "Basic bWVzdHJlOnRvdHZz",
    "Host": "totvs.brazilsouth.cloudapp.azure.com:8051",
    "Connection": "Keep-Alive",
    "User-Agent": "Apache-HttpClient/4.1.1 (java 1.5)"
  },
  body: utf8.encode(requestBody),
  encoding: Encoding.getByName("UTF-8")).then((onValue)
{
  print("Response status: ${onValue.statusCode}");
  print("Response body: ${onValue.body}");
 });

At this point I just receive 411 code:

<hr><p>HTTP Error 411. The request must be chunked or have a content length.</p>

So, I have 2 big doubts :

  1. How can I pass Authentication (user/password);
  2. Why, even setting "Content-Length" hardcoded it always return 411.

I'm new in Dart/Flutter



Solution 1:[1]

After a lot of hours spended in tests, I got success by using this header:

     "SOAPAction": "http://www.totvs.com/IwsConsultaSQL/RealizarConsultaSQL",
    "Content-Type": "text/xml;charset=UTF-8",
    "Authorization": "Basic bWVzdHJlOnRvdHZz",
    "cache-control": "no-cache"

It seams that Content-Length is send automatically, so, the code that worked is this:

  http.Response response = await http.post(
      request,
      headers: {
        "SOAPAction": "http://www.totvs.com/IwsConsultaSQL/RealizarConsultaSQL",
        "Content-Type": "text/xml;charset=UTF-8",
        "Authorization": "Basic bWVzdHJlOnRvdHZz",
        "cache-control": "no-cache"
      },
      body: utf8.encode(requestBody),
      encoding: Encoding.getByName("UTF-8")
  ).then((onValue)
  {
    print("Response status: ${onValue.statusCode}");
    print("Response body: ${onValue.body}");

  });

Thanks all for the help, I got the solution by a Postman code, as suggested before, thanks.

Solution 2:[2]

You are setting too many headers, as most of them will be set by the client - notably the content length and encoding.

Your Basic auth header looks OK.

Don't mix await and then - use one or the other.

You could simplify your code to:

import 'dart:convert';
import 'package:http/http.dart' as http;

main() async {
  String soap = '''<?xml version="1.0"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:tot="http://www.totvs.com/">
  <soapenv:Header/>
  <soapenv:Body>
    <tot:RealizarConsultaSQL>      
      <tot:codSentenca>ETHOS.TESTE</tot:codSentenca>    
      <tot:codColigada>0</tot:codColigada>       
      <tot:codSistema>F</tot:codSistema>       
      <tot:parameters></tot:parameters>
    </tot:RealizarConsultaSQL>
  </soapenv:Body>
</soapenv:Envelope>''';

  http.Response response = await http.post(
    'http://totvs.brazilsouth.cloudapp.azure.com:8051/wherever',
    headers: {
      'content-type': 'text/xmlc',
      'authorization': 'bWVzdHJlOnRvdHZz',
      'SOAPAction': 'http://www.totvs.com/IwsConsultaSQL/RealizarConsultaSQL',
    },
    body: utf8.encode(soap),
  );
  print(response.statusCode);
}

Beware that Dart http lowercases all header names (as allowed by the RFC) but this confuses some servers.

Try your request using Postman. If you can get it to work there, edit the question showing a good Postman request (or another language).

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Daniel Carvalho
Solution 2 Richard Heap