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

Web Kit Form Boundary Support? #1537

Open
GenerelSchwerz opened this issue May 2, 2022 · 2 comments
Open

Web Kit Form Boundary Support? #1537

GenerelSchwerz opened this issue May 2, 2022 · 2 comments

Comments

@GenerelSchwerz
Copy link

I'm facing an issue when using the reqwest::multipart part of this library. I'm currently attempting to make a POST request to a website that only accepts Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryXXXXXXXXXXXX.

Reqwest's current support for multipart data automatically derives the boundary and such using a standard that does not comply with what WebkitFormBoundary desires.

Current multipart boundary generation:

fn gen_boundary() -> String {
    use crate::util::fast_random as random;

    let a = random();
    let b = random();
    let c = random();
    let d = random();

    format!("{:016x}-{:016x}-{:016x}-{:016x}", a, b, c, d)
}

The request I'm attempting to emulate:

curl 'https://canary.discord.com/api/v9/interactions' \
  -H 'authority: canary.discord.com' \
  -H 'x-super-properties: eyJvcyI6IkxpbnV4IiwiYnJvd3NlciI6IkRpc2NvcmQgQ2xpZW50IiwicmVsZWFzZV9jaGFubmVsIjoiY2FuYXJ5IiwiY2xpZW50X3ZlcnNpb24iOiIwLjAuMTM1Iiwib3NfdmVyc2lvbiI6IjUuMTUuMzItMS1NQU5KQVJPIiwib3NfYXJjaCI6Ing2NCIsInN5c3RlbV9sb2NhbGUiOiJlbi1VUyIsIndpbmRvd19tYW5hZ2VyIjoiS0RFLHVua25vd24iLCJkaXN0cm8iOiJcIk1hbmphcm8gTGludXhcIiIsImNsaWVudF9idWlsZF9udW1iZXIiOjEyNjQ2MiwiY2xpZW50X2V2ZW50X3NvdXJjZSI6bnVsbH0=' \
  -H 'x-discord-locale: en-US' \
  -H 'x-debug-options: logGatewayEvents,bugReporterEnabled' \
  -H 'accept-language: en-US' \
  -H 'authorization: <insert token here>' \
  -H 'user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) discord/0.0.135 Chrome/94.0.4606.81 Electron/15.5.1 Safari/537.36' \
  -H 'content-type: multipart/form-data; boundary=----WebKitFormBoundarykwAyTISRXus0p8sG' \
  -H 'accept: */*' \
  -H 'origin: https://canary.discord.com' \
  -H 'sec-fetch-site: same-origin' \
  -H 'sec-fetch-mode: cors' \
  -H 'sec-fetch-dest: empty' \
  -H 'referer: https://canary.discord.com/channels/955145480940191768/968518565349175386' \
  -H 'cookie: __dcfduid=d954a700b87911ec802a21102b798aa2; __sdcfduid=d954a701b87911ec802a21102b798aa26512292cd369303989d7bcaa9d0b23f35a19ba3f82f583bade6d58374394da19; __stripe_mid=529d07b4-7ac5-4792-8c86-cae4ab8234f77bd1d2; __cf_bm=9VnuEGwtDWWAir33kr3V4xNhu4DM8LJlhTJYIn5Alr0-1651495304-0-AehyMRJKc56uT51nmX3QOjN+0jViPy9GQ9QYvrlwUObPrBk0AZquE3wcl+j85lqXSryqUp2Lze7ArCwx+XKjqTS4DgEbvHqR/fyHA0aBzZAx6L+OEA087xymdRs2KNl0Xw==' \
  --data-raw $'------WebKitFormBoundarykwAyTISRXus0p8sG\r\nContent-Disposition: form-data; name="payload_json"\r\n\r\n{"type":2,"application_id":"276060004262477825","guild_id":"955145480940191768","channel_id":"968518565349175386","session_id":"f79084f31c7a8f41f8e7a3a4a2bfca16","data":{"version":"969007199709962270","id":"955966192806404190","name":"reddit","type":1,"options":[{"type":1,"name":"test","options":[{"type":3,"name":"reddit","value":"e"}]}],"application_command":{"id":"955966192806404190","application_id":"276060004262477825","version":"969007199709962270","default_permission":true,"default_member_permissions":"32","type":1,"name":"reddit","description":"📰 Follow subreddits in your Discord server.","dm_permission":false,"options":[{"type":1,"name":"list","description":"📰 List followed subreddits."},{"type":1,"name":"follow","description":"📰 Follow a subreddit in a channel.","options":[{"type":3,"name":"name","description":"The name of the subreddit.","required":true},{"type":7,"name":"channel","description":"The channel to post submissions.","required":true,"channel_types":[0]},{"type":3,"name":"type","description":"The type of the subreddit. (Defaults to Slow)","choices":[{"name":"Slow (1 hour)","value":"slow"},{"name":"Fast (2 mins) (Premium only)","value":"fast"}]},{"type":3,"name":"filters","description":"The filters to use, separated with commas. (Example: one piece, manga, chapter, new)"},{"type":3,"name":"message","description":"The message to send along with every submission. (Example: New submission on /r/OnePiece subreddit\u0021)"},{"type":5,"name":"everyone","description":"Either to mention @everyone along with every submission. (Defaults to False)"},{"type":3,"name":"roles","description":"The roles to mentions along with every submission. (Example: @Role1 @Role2)"},{"type":3,"name":"nsfw","description":"NSFW Filtering to use on new submissions.","choices":[{"name":"Post everything","value":"none"},{"name":"Only post NSFW submissions","value":"only"},{"name":"Ignore NSFW submissions","value":"ignore"}]},{"type":3,"name":"spoiler","description":"Spoiler Filtering to use on new submissions.","choices":[{"name":"Post everything","value":"none"},{"name":"Only post Spoiler-tagged submissions","value":"only"},{"name":"Ignore Spoiler-tagged submissions","value":"ignore"}]}]},{"type":1,"name":"unfollow","description":"📰 Unfollow a subreddit.","options":[{"type":3,"name":"reddit","description":"Subreddit to unfollow.","required":true,"autocomplete":true}]},{"type":1,"name":"test","description":"📰 Test a subreddit.","options":[{"type":3,"name":"reddit","description":"Subreddit to test.","required":true,"autocomplete":true}]}]},"attachments":[]},"nonce":"970612694862266368"}\r\n------WebKitFormBoundarykwAyTISRXus0p8sG--\r\n' \
  --compressed

Is there any alternative for sending multipart forms, or to manually construct them?

@GenerelSchwerz
Copy link
Author

A slight update:

This could be easily resolved if there was an option to specify the boundary of each part manually.
I'm not sure if I should open a pull request or not, since I'm relatively new to rust, but if I should please let me know.

@Coops0
Copy link

Coops0 commented Oct 4, 2023

This is old but the solution I found was to use the mpart-async library, specify my own content type header, and then use the body function with reqwest.

Here is an example:

use mpart_async::client::MultipartRequest;
use mpart_async::filestream::FileStream;
use reqwest::{Body, Client, get, header};
use reqwest::header::CONTENT_TYPE;

pub async fn update_name(
    fields: Vec<(String, String)>,
) -> Result<ResultStruct> {
    let mut mpart = MultipartRequest::<FileStream>::new("------WebKitFormBoundaryhSUnLTjMGhbdZ0Qg");
    for (name, value) in fields {
        mpart.add_field(name, value);
    }

    let res = Client::new()
        .post(format!("website"))
        .header(
            CONTENT_TYPE,
            format!("multipart/form-data; boundary={}", mpart.get_boundary()),
        )
        .body(Body::wrap_stream(mpart))
        .send()
        .await?
        .json::<ResultStruct>()
        .await?;

    Ok(res)
}

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