|  |  |  | libsoup Reference Manual |  | 
|---|
| libsoup 2.2 to 2.4 porting notesPorting notes — Notes on porting from libsoup 2.2 to 2.4 | 
After many API-compatible releases in the 2.2 series, libsoup has now changed its API and bumped its version number to 2.4. Changes were made for a variety of reasons:
To fix bugs and add features that couldn't be done ABI-compatibly.
To make it easier to generate bindings for libsoup for languages other than C.
To clean up ugly/confusing old APIs
To be more glib/gobject/gtk-like in general.
SoupMessage has had a number of API changes made, mostly to increase its language-bindability.
    SoupMessage's
    request_headers and
    response_headers fields are now an
    opaque type (SoupMessageHeaders)
    rather than being GHashTables. The method names have
    changed slightly to reflect this:
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | 
    soup_message_get_header_list has no equivalent;
    if multiple copies of a header are present,
    soup_message_headers_get will return all of
    them, concatenated together and separated by commas; RFC 2616 says
    that the two forms (multiple headers, and a single header with
    comma-separated values) are equivalent; this change to libsoup
    ensures that applications will treat them as equivalent.
In addition, certain important header fields now have dedicated get/set methods:
    (soup_message_headers_set_expectation(msg, SOUP_EXPECTATION_CONTINUE)
    replaces the SOUP_MESSAGE_EXPECT_CONTINUE
    message flag).
    Similarly, the request_body and
    response fields (renamed from
    request and response) are
    now a new type, SoupMessageBody,
    implemented in terms of SoupBuffer, a refcounted
    memory buffer type with clearer semantics than the old
    SoupDataBuffer/SoupOwnership.
| 
 | |
| 
 | 
	    →  | 
| 
 | 
	    →  | 
    A fourth SoupMemoryUse value is also available: SOUP_MEMORY_TEMPORARY,
    which helps to avoid extra copies in some cases.
    SOUP_MEMORY_TEMPORARY means that the memory
    will last at least as long as the object you are handing it to (a
    SoupBuffer, SoupMessageBody, or
    SoupMessage), and so doesn't need to be copied right
    away, but that if anyone makes a copy of the buffer,
    libsoup needs to make a new copy of the
    memory for them at that point, since the original pointer may not
    remain valid for the lifetime of the new copy.
(In the future, there may be additional SoupBuffer and SoupMessageBody methods to work directly with mmapped memory, splicing to file descriptors, etc.)
    soup_message_set_request
    and soup_message_set_response
    still work roughly like they used to.
    Unlike the old request and
    response fields, the new
    request_body and
    response_body fields are not guaranteed
    to be filled in at all times. (In particular, the
    response_body is not filled in until it
    has been fully read, although you can use soup_message_body_get_chunk
    to iterate through the chunks before that point if you need to.)
    When request_body and
    response_body are
    filled in, they are '\0'-terminated for your
    processing convenience. (The terminating 0 byte is not included in
    their length.)
    The prototype of the SoupMessage::got_chunk
    signal has been changed; it now includes the chunk as a
    SoupBuffer parameter (rather than storing the chunk
    data in msg->response as in 2.2). SOUP_MESSAGE_OVERWRITE_CHUNKS
    is now somewhat poorly named, but still has essentially the same
    semantics: if you set it, each chunk will be discarded after it is
    read, and msg->response_body will not be filled
    in with the complete response at the end of message processing.
The API for sending chunked responses from a SoupServer is also slightly different now:
| 
 | |
| 
 | 
	    →  | 
| 
 | 
    Since the new chunk-sending APIs require you to explicitly pass
    the
    request_headers/request_body
    fields, rather than just assuming you're talking about the
    response body, in theory it is now possible to use chunked
    encoding with the request as well. As of the 2.3.0 release this
    has not yet been tested.
    SoupMessage's
    method field is now an interned
    string, and you can compare the method directly against
    the defines such as SOUP_METHOD_GET
    (eg, in a SoupServer request handler).
    soup_method_get_id and the
    SOUP_METHOD_ID_* macros are now gone.
    soup_message_add_header_handler
    and soup_message_add_status_code_handler
    are now just clever wrappers around
    g_signal_connect. In particular, you now pass
    a signal name to them rather than a SoupHandlerPhase,
    and you remove them with the normal signal handler remove methods.
    However, they still retain the special behavior that if the
    message has been cancelled or requeued when the time comes for the
    handler to run, then the handler will be skipped. (Use plain
    g_signal_connect if you don't want that
    behavior.)
    soup_message_io_pause and
    soup_message_io_unpause have been moved to
    SoupSession and SoupServer, to better
    reflect the fact that the session/server control the I/O, and
    SoupMessage is merely acted-upon by them.
| 
 | |
| 
 | 
	    →  | 
    msg->status (the I/O status) is now
    gone as well, because (a) it's really an internal state of
    SoupSession, and (b) it's too easy to confuse
    with msg->status_code (the HTTP status)
    anyway. Code that used to check if status was
    SOUP_MESSAGE_STATUS_FINISHED needs to
    be rewritten to track whether or not the finished
    signal has been emitted.
soup_session_queue_message callback
    soup_session_queue_message's
    callback parameter now includes the SoupSession as a
    parameter, reflecting the fact that it is a
    SoupSession callback, not a SoupMessage
    callback. (It has also been renamed, from
    SoupMessageCallbackFn to SoupSessionCallback.)
    SoupSession's authenticate and
    reauthenticate signals have been merged into a
    single authenticate
    signal with a retrying parameter to indicate if
    it's the second (or later) try. Also, the signal now includes a
    SoupAuth directly,
    and you authenticate by calling soup_auth_authenticate
    on the auth (rather than passing back a username and password from
    the signal handler).
SoupLogger is a
new object that copies the behavior of
evolution-exchange's
E2K_DEBUG and its clones. That is, it causes a
SoupSession to start logging some or all of its HTTP
traffic to stdout, for debugging purposes.
    SoupMessageFilter is gone; code that used to use it
    can now connect to the SoupSession::request-started
    signal to get a chance to act on each message as it is sent.
    (This is how SoupLogger works.)
	    It no longer fully-decodes %-encoded URI components. This
	    is necessary to ensure that complicated URIs (eg, URIs
	    that include other URIs as query parameters) can be
	    round-tripped correctly. This corresponds to the old
	    broken_encoding behavior, but
	    that flag no longer exists, since it is the default and
	    there's no way to turn it off.
	
	    In theory, this is an ABI-breaking change, especially for
	    SoupServers.
	    However, it is unlikely to actually break anything. (And
	    in the SoupServer case, servers now
	    fully-decode the path component
	    themselves unless you set the SOUP_SERVER_RAW_PATHS
	    flag on the server, so the behavior should still be the
	    same.
	
It uses the RFC3986 parsing rules, including support for IPv6 literal addresses.
	    The field formerly called
	    protocol is now
	    scheme, to match the spec, and
	    it's an interned string rather than a quark. The names of
	    the predefined values have changed to match:
	
| 
 | |
| 
 | 
soup_uri_decode
now returns a new string rather than modifying its input string in
place. The new method soup_uri_normalize,
which removes some, but not all, %-encoding, behaves similarly.
Finally, SoupURI (as well as most other struct types in
libsoup) now uses the glib "slice"
allocator, so any code that uses g_new to create
SoupURIs is wrong. If you want to create a URI "by hand",
you can call soup_uri_new,
passing NULL, and you will get back an empty
SoupURI. There are also now methods that can be used to
set its fields (eg, soup_uri_set_scheme,
soup_uri_set_path,
etc) rather than mucking with the fields directly.
Related to SoupURI, there are some new helper methods for
dealing with HTML forms. soup_form_decode_urlencoded
decodes a URI query component (or an
application/x-www-form-urlencoded request body)
into a GHashTable. soup_form_encode_urlencoded
reverses the process, allowing you to fill in a
uri->query with a properly-encoded form dataset.
(SoupURI also provides soup_uri_set_query_from_form
to help with this.)
SOAP support has been removed; the existing methods covered only a teeny tiny subset of SOAP, which was really only useful to a single application. (The code that was formerly in libsoup has been moved to that application.). If you were using this code, you can resurrect a libsoup-2.4-compatible version of it from revision 1016 of libsoup svn.
The XML-RPC code has been completely rewritten to make it simpler to implement XML-RPC clients and servers. (Note: the server-side code has not been heavily tested yet.) The new XML-RPC API makes use of GValues, with the following type mappings:
| 
 | 
	    → int ( | 
| 
 | 
	    → gboolean ( | 
| 
 | 
	    → char * ( | 
| 
 | 
	    → double ( | 
| 
 | 
	    → SoupDate ( | 
| 
 | 
	    → GByteArray ( | 
| 
 | 
	    → GHashTable ( | 
| 
 | 
	    → GValueArray ( | 
SoupDate is discussed below.
SOUP_TYPE_BYTE_ARRAY is just a new
GType value defined by libsoup
to represent GByteArrays, which glib does not define a
GType for.
libsoup provides some additional GValue support
methods for working with
GValueArrays, and GHashTables of
GValues, for the XML-RPC struct and
array types. Eg, you can use soup_value_hash_new
to create a GHashTable to use with the XML-RPC methods,
and soup_value_hash_insert
to add values to it without needing to muck with GValues
directly.
The getbug and xmlrpc-test
programs in the libsoup sources provide
examples of how to use the new API. (Beware that
xmlrpc-test's use of the API is a little
complicated because of the way it sends all calls through a single
do_xmlrpc method.)
    The prototypes for soup_server_add_handler,
    and for the SoupServer
    handlers themselves have changed:
typedef void (*SoupServerCallback) (SoupServer *server, SoupMessage *msg, const char *path, GHashTable *query, SoupClientContext *client, gpointer user_data); void soup_server_add_handler (SoupServer *server, const char *path, SoupServerCallback callback, gpointer data, GDestroyNotify destroy);
    soup_server_add_handler no longer takes a
    SoupServerAuthContext (see the discussion of server
    authentication below), and the order of the final two arguments
    has been swapped. (Additionally, SoupServerCallbackFn
    has been renamed to SoupServerCallback, and the old
    unregister parameter of type
    SoupServerUnregisterFn is now a standard
    GDestroyNotify. The change to
    GDestroyNotify and the swapping of the final two
    arguments is to make the method conform to standard glib/gtk
    practices.)
    In SoupServerCallback, several bits of data that used
    to be part of the context argument are now
    provided directly, and context specifically
    only contains more specifically-client-related information (such
    as the SoupSocket that the request arrived on, and
    information about authentication).
    path is the fully %-decoded path component
    of msg's URI, and
    query is a hash table containing
    msg's URI's
    query component decoded with soup_form_decode_urlencoded.
    These are provided for your convenience; if you need the raw
    query, you can get it out of msg's URI
    directly. If you need the raw path, you'll need to set the SOUP_SERVER_RAW_PATHS
    property on the server, which actually changes the behavior of the
    server with respect to how paths are matched; see the
    documentation for details.
    SoupServer authentication has been completely
    rewritten, with SoupServerAuthContext being replaced
    with SoupAuthDomain. Among
    other improvements, you no longer need to have the cleartext
    password available to check against. See the
    SoupAuthDomain documentation, the server tutorial, and
    tests/server-auth-test.c.
Expect: 100-continue and other early SoupMessage processing
    SoupServer now handles
    "Expect: 100-continue" correctly. In
    particular, if the client passes that header, and your server
    requires authentication, then authentication will be checked
    before reading the request body.
    If you want to do additional pre-request-body handling, you can
    connect to SoupServer's request_started
    signal, and connect to the request's got_headers
    signal from there. (See the description of
    request_started for information about other
    related SoupServer signals.)
    SoupServer now automatically sets the
    Date header on all responses, as required by
    RFC 2616.
    SoupServerMessage is now merged into
    SoupMessage.
    soup_server_message_set_encoding is replaced
    with soup_message_headers_set_encoding
    as described in the section on SoupMessage above.
soup_server_run / soup_server_quit
    soup_server_run
    and soup_server_run_async
    no longer g_object_ref the server, and
    soup_server_quit
    no longer unrefs it.
    The new SoupDate type
    replaces the old soup_date_* methods, and has
    an improved (more liberal) date parser.
SoupSocket has had various simplifications made to reflect the fact that this is specifically libsoup's socket implementation, not some random generic socket API.
    Various SoupAddress and SoupSocket
    methods now take arguments of the new GCancellable type, from
    libgio. When porting old code, you can just pass
    NULL for these. (soup_address_resolve_async
    also takes another new argument, a GMainContext that
    you'll want to pass NULL for.) If you pass a
    GCancellable, you can use it to cleanly cancel the
    address resolution / socket operation.