HTTP Upload vs. SOAP Request (how they are different)

What is the difference between an HTTP Upload and a SOAP Request?

An upload is an HTTP request that uses the multipart/form-data content-type. (All HTTP requests and responses are MIME, and the format of a given request is determined by the content-type.) A SOAP request, on the other hand, has a content-type of text/xml, which means it is composed of a MIME header + body, where the body contains the SOAP XML. Whereas an upload is a multipart MIME structure, where each sub-part contains either the content of a file, or a name/value parameter.

Here are some examples. First a very simple HTTP upload as produced by this C++ fragment:

CkUpload upload;
CkUrl url;

url.ParseUrl("https://www.some-web-server.com/receiveTheUpload.aspx");

upload.put_Hostname(url.host());
upload.put_Path(url.path());
upload.put_Port(url.get_Port());

upload.AddCustomHeader("MyCustomRequestHeader","abc 123");

upload.AddFileReference("TinyA","qa_data/xml/tinyA.xml");

CkByteData uploadData;
upload.UploadToMemory(uploadData);
uploadData.saveFile("qa_output/uploadData1.txt");

The HTTP request (which is MIME, and by the way, and emails are also composed of MIME, so understanding a bit about MIME will do one good because it is so central to Internet technologies..) looks like this:

POST /receiveTheUpload.aspx HTTP/1.1
Host: www.some-web-server.com
User-Agent: ChilkatUpload/3.0 (http://www.chilkatsoft.com/)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Connection: keep-alive
Expect: 100-continue
MyCustomRequestHeader: abc 123
Content-Type: multipart/form-data; boundary=---------------------------DD1A174A4121EDFD
Content-Length: 206

-----------------------------DD1A174A4121EDFD
Content-Disposition: form-data; name="TinyA"; filename="tinyA.xml"
Content-Type: text/xml

<tiny>A</tiny>
-----------------------------DD1A174A4121EDFD--

A SOAP XML request, as sent by this fragment of C++ code:

CkHttp http;

http.put_SessionLogFilename("qa_output/xmlPostLog.txt");

// The URL used here is junk and will result in a 404 not found. 
// (We don't care about the response, we
// are only interested in understanding the format of the HTTP request sent.)
// Imagine the XML passed in the 2nd argument is actually a SOAP XML document... 

CkHttpResponse *resp = http.PostXml("http://www.chilkatsoft.com/mywebservice",
    "<tiny>A</tiny>","utf-8");
delete resp;

Looks like this:

(Imagine the XML is actually a SOAP XML document..)

POST /mywebservice HTTP/1.1
Content-Type: text/xml
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip
Host: www.chilkatsoft.com
Content-Length: 14

<tiny>A</tiny>

An HTTP upload containing two file is produced by this fragment of code:

CkUpload upload;
CkUrl url;

url.ParseUrl("https://www.some-web-server.com/receiveTheUpload.aspx");

upload.put_Hostname(url.host());
upload.put_Path(url.path());
upload.put_Port(url.get_Port());

upload.AddCustomHeader("MyCustomRequestHeader","abc 123");

upload.AddFileReference("TinyA","qa_data/xml/tinyA.xml");
upload.AddFileReference("TinyB","qa_data/xml/tinyB.xml");

CkByteData uploadData;
upload.UploadToMemory(uploadData);
uploadData.saveFile("qa_output/uploadData2.txt");

And the HTTP request looks like this:

POST /receiveTheUpload.aspx HTTP/1.1
Host: www.some-web-server.com
User-Agent: ChilkatUpload/3.0 (http://www.chilkatsoft.com/)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Connection: keep-alive
Expect: 100-continue
MyCustomRequestHeader: abc 123
Content-Type: multipart/form-data; boundary=---------------------------6F87F47E0974A38B
Content-Length: 363

-----------------------------6F87F47E0974A38B
Content-Disposition: form-data; name="TinyA"; filename="tinyA.xml"
Content-Type: text/xml

<tiny>A</tiny>
-----------------------------6F87F47E0974A38B
Content-Disposition: form-data; name="TinyB"; filename="tinyB.xml"
Content-Type: text/xml

<tiny>B</tiny>
-----------------------------6F87F47E0974A38B--

Finally, an HTTP upload with multiple files and a few name/value params is produced by this C++ fragment:

CkUpload upload;

CkUrl url;

url.ParseUrl("https://www.some-web-server.com/receiveTheUpload.aspx");

upload.put_Hostname(url.host());
upload.put_Path(url.path());
upload.put_Port(url.get_Port());

upload.AddCustomHeader("MyCustomRequestHeader","abc 123");

upload.AddParam("ParamA","This is the value for param A");
upload.AddParam("ParamB","This is the value for param B");

upload.AddFileReference("TinyA","qa_data/xml/tinyA.xml");
upload.AddFileReference("TinyB","qa_data/xml/tinyB.xml");

CkByteData uploadData;
upload.UploadToMemory(uploadData);
uploadData.saveFile("qa_output/uploadData3.txt");

And the HTTP request looks like this:

POST /receiveTheUpload.aspx HTTP/1.1
Host: www.some-web-server.com
User-Agent: ChilkatUpload/3.0 (http://www.chilkatsoft.com/)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Connection: keep-alive
Expect: 100-continue
MyCustomRequestHeader: abc 123
Content-Type: multipart/form-data; boundary=---------------------------EFC8C527CC836355
Content-Length: 617

-----------------------------EFC8C527CC836355
Content-Disposition: form-data; name="ParamA"

This is the value for param A
-----------------------------EFC8C527CC836355
Content-Disposition: form-data; name="ParamB"

This is the value for param B
-----------------------------EFC8C527CC836355
Content-Disposition: form-data; name="TinyA"; filename="tinyA.xml"
Content-Type: text/xml

<tiny>A</tiny>
-----------------------------EFC8C527CC836355
Content-Disposition: form-data; name="TinyB"; filename="tinyB.xml"
Content-Type: text/xml

<tiny>B</tiny>
-----------------------------EFC8C527CC836355--

v9.5.0.35 Micro Update: HTTP Resume Download – Fixed PercentDone Event Callback

The PercentDone callback always began at 0 when resuming a download. If a partial file exists locally, and the download is resumed, the percent done now begins at the place based on the size of the partial file. (If 50% of the file already exists, then the percent done begins at 50%)

Also, the Socket.BuildHttpGetRequest method was re-introduced. This is a convenience method for building a simple HTTP GET request. For any more complex HTTP GET requests, use the Chilkat.HttpRequest object instead. (This method was removed temporarily due to cross-linkage with all of the internal HTTP infrastructure which caused additional unused baggage to be linked into an executable. It was rewritten to avoid this linkage.)

v9.5.0.34 Micro Update: SSL/TLS Perfect Forward Secrecy, Minor HTTP and ASN.1 Fixes

The internal Chilkat SSL/TLS implementation now supports the TLS_DHE_RSA_WITH_AES_256_CBC_SHA and TLS_DHE_RSA_WITH_AES_128_CBC_SHA cipher suites. These allow for perfect forward secrecy. Note: This is implemented on the client-side for all protocols using SSL/TLS. The SSL/TLS client provides the server with a list of algorithms it supports, and it is the server that decides which is to be used. These new algorithms are now included in the list, and will be used if the server chooses.

Also, a minor problem was fixed in Chilkat HTTP. If a server responds with no Content-Length header, then there was a chance that Chilkat would not return the full response. This does not apply to “chunked” responses — only to non-chunked responses that are lacking the Content-Length header — which is a rare occurrence (and it is poor practice for an HTTP response to omit the Content-Length).

Finally, a minor and rarely encountered ASN.1 problem was fixed. (ASN.1 code is internal to Chilkat and has to do with implementations for PKCS, PFX, etc.

v9.5.0.32 Micro Update: HTTP Connection Left in Invalid State after Event Callback Aborts Operation

For HTTP requests that have KeepAlive indicated in the response header, the internal connection is not closed so that a subsequent request may continue using the existing connection. However, when the client application aborts in the middle of receiving the response, the connection must be closed to avoid being left in an invalid state (where the some of the remainder of the aborted request may have already been received and would incorrectly be read as the first bytes of the nexxt response). The internal fix was to always close the connection after an abort so that the next HTTP operation starts afresh on a new connection.

v9.4.1.44 Added Http.AwsEndpoint Property

The AwsEndpoint property is the regional endpoint (domain) to be used for Amazon S3 method calls. The default value is “s3.amazonaws.com”. This can be set to any valid Amazon S3 endpoint, such as “s3-eu-west-1.amazonaws.com”, or the endpoints for S3-API compatible services from other different providers.

This is a pre-release feature. Pre-release builds are made available upon request (support@chilkatsoft.com). Please make sure to specify the exact build needed (programming language, operating system, architecture, .NET Framework, Visual Studio Version, or anything else that may be required to know exactly which build is required).

WebDAV Sample using Chilkat HTTP

ASP: WebDAV PROPFIND
SQL Server: WebDAV PROPFIND
C#: WebDAV PROPFIND
C++: WebDAV PROPFIND
Objective-C: WebDAV PROPFIND
IOS: WebDAV PROPFIND
PowerShell: WebDAV PROPFIND
MFC: WebDAV PROPFIND
C: WebDAV PROPFIND
Delphi: WebDAV PROPFIND
Visual FoxPro: WebDAV PROPFIND
Java: WebDAV PROPFIND
Android™: WebDAV PROPFIND
Perl: WebDAV PROPFIND
PHP: WebDAV PROPFIND
PHP: WebDAV PROPFIND
Python: WebDAV PROPFIND
Ruby: WebDAV PROPFIND
VB.NET: WebDAV PROPFIND
Visual Basic: WebDAV PROPFIND
VBScript: WebDAV PROPFIND

Understanding URL Syntax (and Arguments to Http.SynchronousRequest)

URL’s have this general format:

<scheme>://<domain>:<port>/<path>?<query_string>#<fragment_id>

The URL parts are summarized below.  Comments about how each part relates to the SynchronousRequest method are included.  The SynchronousRequest method has the following signature (C# syntax)

HttpResponse SynchronousRequest(string domain, int port, bool ssl, HttpRequest req);

The URL parts:

  • scheme:  This can be “http” or “https”.   If “https”, then SSL/TLS is used and the “ssl” argument to SynchronousRequest should be set to true.
  • domain:  The domain name or dotted IP address of the web server hosting the resource.  This is the domain argument to SynchronousRequest
  • port: The port number on which the server is listening.  If not explicitly specified, the default for non-SSL is 80, the default for SSL/TLS is 443.  This value must be explicitly passed in the port argument to SynchronousRequest.
  • path:  The local name for the resource on the server.  In SynchronousRequest, the path is passed in the Path property of the HttpRequest object (which is the last argument to SynchronousRequest).
  • query_string:  It may contain name/value pairs separated by ampersands, for example first_name=John&last_name=Doe.  If SynchronousRequest is sending a GET request (where the HttpRequest.HttpVerb = “GET”, then the HttpRequest.Path property should contain the entire path + query string.
  • fragment_id:  A name for a piece or part of the resource.  The fragment_id is never passed to the server and is only used by the client (i.e. the browser).  Typically, it’s to automatically navigate to a specific anchor within the HTML page.

Posting a status update to Twitter

ASP: HTTP POST Twitter Status Update
SQL Server: HTTP POST Twitter Status Update
C#: HTTP POST Twitter Status Update
C++: HTTP POST Twitter Status Update
MFC: HTTP POST Twitter Status Update
C: HTTP POST Twitter Status Update
Delphi: HTTP POST Twitter Status Update
Visual FoxPro: HTTP POST Twitter Status Update
Java: HTTP POST Twitter Status Update
Perl: HTTP POST Twitter Status Update
PHP: HTTP POST Twitter Status Update
Python: HTTP POST Twitter Status Update
Ruby: HTTP POST Twitter Status Update
VB.NET: HTTP POST Twitter Status Update
Visual Basic: HTTP POST Twitter Status Update
VBScript: HTTP POST Twitter Status Update