Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

client-only permessage-deflate still sends server headers #2671

Open
bgemmill opened this issue Apr 21, 2023 · 5 comments
Open

client-only permessage-deflate still sends server headers #2671

bgemmill opened this issue Apr 21, 2023 · 5 comments

Comments

@bgemmill
Copy link

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
Copy link
Author

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);
      }));

@klemens-morgenstern
Copy link
Collaborator

have you tried setting server_max_window_bits on the pd_option struct ?

@bgemmill
Copy link
Author

@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.

@klemens-morgenstern
Copy link
Collaborator

Sorry for the late response.

The decorator solves it?

@bgemmill
Copy link
Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants