SOAP Request in Flutter/Dart

12,524

Solution 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

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).

Share:
12,524

Related videos on Youtube

Daniel Carvalho
Author by

Daniel Carvalho

Updated on June 04, 2022

Comments

  • Daniel Carvalho
    Daniel Carvalho almost 2 years

    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

    • Magillus
      Magillus over 5 years
      Can you sniff out the http call via wireshark or Charles or other tool? Maybe the "Content-Length" is calculated already by http.post?
    • JRomero
      JRomero over 5 years
      Try looking at what your data looks like on webhook.site
  • Daniel Carvalho
    Daniel Carvalho over 5 years
    I´ve got the same ansewer from the server. HTTP Error 411. The request must be chunked or have a content length. So I still have to find out why... Any clues?
  • Richard Heap
    Richard Heap over 5 years
    can you share what the actual value of 8051/whatever is?
  • Nick
    Nick about 5 years
    do you hav any detail example of how to consuming soap with dart? thanks