## Migrating from libsoup 2

### Removed APIs

This is a list of APIs that have been removed:

- XML-RPC support

- Handling of `file://` and `data://` URIs

  You should use GFile for the former and `soup_uri_decode_data_uri()` for the latter.

- Define aliases for property names

  You must use the string name of properties directly which works in libsoup 2 already.

- `SoupSession:add-feature` and `SoupSession:add-feature-by-type`

  You must call `soup_session_add_feature()` and `soup_session_add_feature_by_type()` directly.

- SoupRequest

  You should use `soup_session_send()` or `soup_session_send_async()` methods.

- SoupAddress has been replaced with GInetAddress and GNetworkAddress

- SoupSocket has been removed

- SoupProxyResolverDefault is replaced by `g_proxy_resolver_get_default()`

- SoupBuffer has been replaced by GBytes and GByteArray

- SoupDate has been replaced by GDateTime

- `SoupSession:ssl-strict` has been removed in favor of using the `SoupMessage:accept-certificate` signal.

- `soup_session_cancel_message()` has been removed

  Instead you pass a GCancellable to APIs and call `g_cancellable_cancel()`.

### Moved authenticate signal

The `SoupSession::authenticate` signal has been replaced by `SoupMessage::authenticate`. It now allows returning `TRUE` to signifiy if you will handle authentication which allows for asynchronous handling.

### Structs are private

You can no longer directly access various structs such as SoupMessage. These are now accessed by getters and setters. See below for direct conversions:

Struct field | Getter/Setter function
--- | ---
SoupMessage.method | `soup_message_get_method()`
SoupMessage.status_code | `soup_message_get_status()`
SoupMessage.reason_phrase | `soup_message_get_reason_phrase()`
SoupMessage.uri | `soup_message_get_uri()`, `soup_message_set_uri()`
SoupMessage.request_headers | `soup_message_get_request_headers()`
SoupMessage.response_headers | `soup_message_get_response_headers()`
SoupMessage.request_body | `soup_message_set_request_body()`, `soup_message_set_request_body_from_bytes()`
SoupMessage.response_body | See section on IO

Similar struct changes exist for SoupCookie but have very straightforward replacements.

### URI type changed

The SoupURI type has been replaced with the GUri type which has some implications.

Creating a GUri is generally as simple as `g_uri_parse (uri, SOUP_HTTP_URI_FLAGS, NULL)`. You may want to add `G_URI_FLAGS_PARSE_RELAXED` to accept input that used to be considered valid.

Note that unlike SoupURI GUri is an immutable type so you cannot change the contents of one after it has been constructed. We provide `soup_copy_uri()` to aid in modifying them.

The equivalent behavior to `soup_uri_to_string (uri, FALSE)` is `g_uri_to_string_partial (uri, G_URI_HIDE_PASSWORD)`.

Since GUri does not provide any function to check for equality `soup_uri_equal()` still exists.

Sending a `OPTIONS` message with a path of `*` is no longer a valid URI and has been replaced with SoupMessage:options-ping.

### Status codes no longer used for internal errors

Previously SoupStatus was used to hold libsoup errors (`SOUP_STATUS_IS_TRANSPORT_ERROR()`). Now all of these errors are propagated up through the normal GError method on the various APIs to send messages. Here is a mapping chart between the status codes and new errors:

Old Status Codes | New GError
--- | ---
`SOUP_STATUS_CANCELLED` | `G_IO_ERROR_CANCELLED`
`SOUP_STATUS_MALFORMED` | `SOUP_SESSION_ERROR_PARSING`, `SOUP_SESSION_ERROR_ENCODING`
`SOUP_STATUS_TOO_MANY_REDIRECTS` | `SOUP_SESSION_ERROR_TOO_MANY_REDIRECTS`

### All IO is now GIOStream-based

Previously there were ways to allow libsoup to read data into buffers and for you to read from those buffers such as `SoupMessage:response-body`, `SoupMessage:response-body-data`, and `SoupMessage::got-chunk`.

libsoup no longer stores a buffer of data for you to read from and instead it returns a GInputStream which you read from using normal GIO APIs.

If you want to simply request a buffer and nothing more you can use the `soup_session_send_and_read()` or `soup_session_send_and_read_async()` APIs.

This also applies to writing data where you can set a GInputStream using `soup_message_set_request_body()` or use the convenience API `soup_message_set_request_body_from_bytes()` to use a GBytes buffer.

### Clarification on thread-safety

In libsoup 2 there was an attempt at making various APIs of the library thread-safe. However this was never well tested, maintained, or documented.

In libsoup 3 it now behaves in line with other GObject libraries. Once you create a SoupSession all usage of that session must happen on the same thread. You may create seperate sessions per thread but in most use-cases you should be using the async APIs which handle non-blocking IO for you.