beast icon indicating copy to clipboard operation
beast copied to clipboard

client-only permessage-deflate still sends server headers

Open bgemmill opened this issue 2 years ago • 6 comments

I'm using boost 1.81 and beast to connect as a client to a remote websocket host, and with compression disabled, everything works fine.

This endpoint supports permessage-deflate from clients, and will also fail to upgrade if any server deflate headers are included.

If I try to add compression like so:

    auto ret = std::make_shared<websocket_t>(io_ctx, ssl_ctx);
    boost::beast::websocket::permessage_deflate pd_option{false, true};
    ret->set_option(pd_option);

The upgrade headers still include server_max_window_bits, and the websocket upgrade is rejected. The issue seems to be in the translation between pd_option and beast's internal pmd_offer; the latter seems to support client and server at once only.

Attempts to set the server window size to 0 to prevent the field from being written (looking at the source of pmd_extension.ipp) yield an invalid value error.

Would it be possible for pmd_offer to respect the pd_option's server_enable flag and not send those headers?

bgemmill avatar Apr 21 '23 17:04 bgemmill

Decorators do the job, but just feel super clunky since the option to use client or server compression was all ready specified.

    // Set a decorator to manually modify the websocket upgrade request for one-sided PMD negotiation
    ret->set_option(boost::beast::websocket::stream_base::decorator(
      [pd_option](boost::beast::websocket::request_type& req) {

        std::string deflate_header("permessage-deflate;");
        if(pd_option.server_enable) {
          deflate_header.append(" server_max_window_bits=");
          deflate_header.append(std::to_string(pd_option.server_max_window_bits));
        }
        if(pd_option.client_enable) {
          deflate_header.append(" client_max_window_bits=");
          deflate_header.append(std::to_string(pd_option.client_max_window_bits));
        }

        req.set(boost::beast::http::field::sec_websocket_extensions, deflate_header);
      }));

bgemmill avatar Apr 22 '23 03:04 bgemmill

have you tried setting server_max_window_bits on the pd_option struct ?

klemens-morgenstern avatar Apr 24 '23 02:04 klemens-morgenstern

@klemens-morgenstern yes, setting it to anything in a valid range has it sent as a header, and attempting to set it to an an invalid value gives beast errors about invalid values.

Aside from the decorator above, I'm not sure how to only send the client PMD header.

bgemmill avatar Apr 24 '23 02:04 bgemmill

Sorry for the late response.

The decorator solves it?

klemens-morgenstern avatar May 10 '23 23:05 klemens-morgenstern

While I can suppress the server headers with the decorator, it seems strange that they're sent at all when we specify no server headers in the permessage_deflate pd_option

bgemmill avatar May 12 '23 02:05 bgemmill