static void server_callback (SoupServer *server, SoupMessage *msg, const char *path, GHashTable *query, SoupClientContext *context, gpointer data) { const char *accept_encoding, *options; GSList *codings; char *file = NULL, *contents; gsize length; options = soup_message_headers_get_one (msg->request_headers, "X-Test-Options"); if (!options) options = ""; accept_encoding = soup_message_headers_get_list (msg->request_headers, "Accept-Encoding"); if (accept_encoding && !soup_header_contains (options, "force-encode")) codings = soup_header_parse_quality_list (accept_encoding, NULL); else codings = NULL; if (codings) { gboolean claim_deflate, claim_gzip; const char *file_path = NULL, *encoding = NULL; claim_deflate = g_slist_find_custom (codings, "deflate", (GCompareFunc)g_ascii_strcasecmp) != NULL; claim_gzip = g_slist_find_custom (codings, "gzip", (GCompareFunc)g_ascii_strcasecmp) != NULL; if (claim_gzip && (!claim_deflate || (!soup_header_contains (options, "prefer-deflate-zlib") && !soup_header_contains (options, "prefer-deflate-raw")))) { file_path = SRCDIR "/resources%s.gz"; encoding = "gzip"; } else if (claim_deflate) { if (soup_header_contains (options, "prefer-deflate-raw")) { file_path = SRCDIR "/resources%s.raw"; encoding = "deflate"; } else { file_path = SRCDIR "/resources%s.zlib"; encoding = "deflate"; } } if (file_path && encoding) { file = g_strdup_printf (file_path, path); if (g_file_test (file, G_FILE_TEST_EXISTS)) { soup_message_headers_append (msg->response_headers, "Content-Encoding", encoding); } else { g_free (file); file = NULL; } } } soup_header_free_list (codings); if (!file) file = g_strdup_printf (SRCDIR "/resources%s", path); if (!g_file_get_contents (file, &contents, &length, NULL)) { /* If path.gz exists but can't be read, we'll send back * the error with "Content-Encoding: gzip" but there's * no body, so, eh. */ g_free (file); soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND); return; } g_free (file); if (soup_header_contains (options, "force-encode")) { const gchar *encoding = "gzip"; if (soup_header_contains (options, "prefer-deflate-zlib") || soup_header_contains (options, "prefer-deflate-raw")) encoding = "deflate"; soup_message_headers_replace (msg->response_headers, "Content-Encoding", encoding); } /* Content-Type matches the "real" format, not the sent format */ if (g_str_has_suffix (path, ".gz")) { soup_message_headers_append (msg->response_headers, "Content-Type", "application/gzip"); } else { soup_message_headers_append (msg->response_headers, "Content-Type", "text/plain"); } soup_message_set_status (msg, SOUP_STATUS_OK); soup_message_headers_set_encoding (msg->response_headers, SOUP_ENCODING_CHUNKED); if (!soup_header_contains (options, "empty")) { soup_message_body_append (msg->response_body, SOUP_MEMORY_TAKE, contents, length); } else g_free (contents); if (soup_header_contains (options, "trailing-junk")) { soup_message_body_append (msg->response_body, SOUP_MEMORY_COPY, options, strlen (options)); } soup_message_body_complete (msg->response_body); }
/** * soup_websocket_client_verify_handshake: * @msg: #SoupMessage containing both client and server sides of a * WebSocket handshake * @error: return location for a #GError * * Looks at the response status code and headers in @msg and * determines if they contain a valid WebSocket handshake response * (given the handshake request in @msg's request headers). * * This is a low-level function; if you use * soup_session_websocket_connect_async() to create a WebSocket * connection, it will call this for you. * * Returns: %TRUE if @msg contains a completed valid WebSocket * handshake, %FALSE and an error if not. * * Since: 2.50 */ gboolean soup_websocket_client_verify_handshake (SoupMessage *msg, GError **error) { const char *protocol, *request_protocols, *extensions, *accept_key; char *expected_accept_key; gboolean key_ok; if (msg->status_code == SOUP_STATUS_BAD_REQUEST) { g_set_error_literal (error, SOUP_WEBSOCKET_ERROR, SOUP_WEBSOCKET_ERROR_BAD_HANDSHAKE, _("Server rejected WebSocket handshake")); return FALSE; } if (msg->status_code != SOUP_STATUS_SWITCHING_PROTOCOLS) { g_set_error_literal (error, SOUP_WEBSOCKET_ERROR, SOUP_WEBSOCKET_ERROR_NOT_WEBSOCKET, _("Server ignored WebSocket handshake")); return FALSE; } if (!soup_message_headers_header_equals (msg->response_headers, "Upgrade", "websocket") || !soup_message_headers_header_contains (msg->response_headers, "Connection", "upgrade")) { g_set_error_literal (error, SOUP_WEBSOCKET_ERROR, SOUP_WEBSOCKET_ERROR_NOT_WEBSOCKET, _("Server ignored WebSocket handshake")); return FALSE; } protocol = soup_message_headers_get_one (msg->response_headers, "Sec-WebSocket-Protocol"); if (protocol) { request_protocols = soup_message_headers_get_one (msg->request_headers, "Sec-WebSocket-Protocol"); if (!request_protocols || !soup_header_contains (request_protocols, protocol)) { g_set_error_literal (error, SOUP_WEBSOCKET_ERROR, SOUP_WEBSOCKET_ERROR_BAD_HANDSHAKE, _("Server requested unsupported protocol")); return FALSE; } } extensions = soup_message_headers_get_list (msg->response_headers, "Sec-WebSocket-Extensions"); if (extensions && *extensions) { g_set_error_literal (error, SOUP_WEBSOCKET_ERROR, SOUP_WEBSOCKET_ERROR_BAD_HANDSHAKE, _("Server requested unsupported extension")); return FALSE; } accept_key = soup_message_headers_get_one (msg->response_headers, "Sec-WebSocket-Accept"); expected_accept_key = compute_accept_key (soup_message_headers_get_one (msg->request_headers, "Sec-WebSocket-Key")); key_ok = (accept_key && expected_accept_key && !g_ascii_strcasecmp (accept_key, expected_accept_key)); g_free (expected_accept_key); if (!key_ok) { g_set_error (error, SOUP_WEBSOCKET_ERROR, SOUP_WEBSOCKET_ERROR_BAD_HANDSHAKE, _("Server returned incorrect \"%s\" key"), "Sec-WebSocket-Accept"); return FALSE; } return TRUE; }