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

Add Content-Type header to all POST requests without an empty body #863

Conversation

AudricV
Copy link
Member

@AudricV AudricV commented Jun 19, 2022

This PR adds the Content-Type header to all POST requests without an empty body made by the extractor. They are made only in YouTube and Bandcamp services, according to the usages of the post methods in the Downloader class.

Currently, in NewPipe and in tests, this header is partially guessed and added by the network library we use, OkHttp. But this is not the case of all network libraries (e.g. Cronet), where 400 responses would be encountered on YouTube because the HTTP specifications for POST requests are not required.

I also improved related code in the changed files, and fixed some issues on the fly.

@AudricV AudricV added bug Issue is related to a bug youtube service, https://www.youtube.com/ bandcamp service, https://bandcamp.com labels Jun 19, 2022
@Stypox
Copy link
Member

Stypox commented Jun 24, 2022

Uhm, instead of all of this duplicate code, shouldn't we change the Downloader.post() methods so that they take a String contentType parameter? Then the implementers of Downloader will take care of setting Content-Length (which can be derived from body.size) and Content-Type (which is the provided value). Since, as you said, having those two headers is a requirement for post requests, imo it makes sense to change the post() signature, so that we will surely not forget to put the content type anymore as the compiler would complain, while the length is set always.

This will not be merged before the next version, I don't think it is a big deal for the NewPipe app. But we can make a specific extractor version after this PR is merged if needed.

@FireMasterK
Copy link
Member

I'm not sure if Content-Length, should be set since for example, what if gzip/brotli is being used by the downloader?

@AudricV AudricV marked this pull request as draft July 5, 2022 19:21
@AudricV AudricV force-pushed the add-content-type-and-content-length-headers-to-post-requests branch from c6cf025 to 438fb69 Compare July 11, 2022 14:35
@AudricV
Copy link
Member Author

AudricV commented Jul 11, 2022

I'm not sure if Content-Length, should be set since for example, what if gzip/brotli is being used by the downloader?

Thank you for the catch! I removed the addition of this header, and kept only the Content-Type one.

@AudricV AudricV marked this pull request as ready for review July 11, 2022 14:37
@AudricV
Copy link
Member Author

AudricV commented Jul 11, 2022

Note that the CI will fail because I didn't updated YoutubeStreamExtractorLivestreamTest, see why in 438fb69 .

@AudricV AudricV changed the title Add Content-Type and Content-Length headers to POST requests Add Content-Type header to all POST requests without an empty body Jul 11, 2022
@AudricV AudricV force-pushed the add-content-type-and-content-length-headers-to-post-requests branch from 438fb69 to b61ee64 Compare July 11, 2022 14:56
Copy link
Member

@Stypox Stypox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just create a utility method in the downloader, something like this:

postWithContentType(url, headers, body, contentType, localization) {
    final Map<String, List<String>> actualHeaders = new HashMap<>(headers);
    actualHeaders.put("Content-Type", Collections.singletonList(contentType));
    post(url, actualHeaders, body, localization);
}

and maybe even this as a shorthand for json requests

postWithContentTypeJson(url, headers, body, localization) {
    postWithContentType(url, headers, body, "application/json", localization);
}

The current strategy contains too much duplicated code.

@AudricV AudricV force-pushed the add-content-type-and-content-length-headers-to-post-requests branch from b61ee64 to 54970e5 Compare July 15, 2022 19:20
@AudricV AudricV requested a review from Stypox July 15, 2022 19:20
Copy link
Member

@Stypox Stypox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, almost ready

@AudricV AudricV force-pushed the add-content-type-and-content-length-headers-to-post-requests branch from 54970e5 to 2ca254e Compare August 7, 2022 22:17
@AudricV
Copy link
Member Author

AudricV commented Aug 7, 2022

Requested changes have been applied.

Note: I reverted update of YoutubeLiveStreamExtractorTest and removal of YoutubeSearchExtractorTest.Suggestion, as both tests will be fixed in #882. That's the reason why some tests will fail because of missing mocks.

@AudricV AudricV requested a review from Stypox August 7, 2022 22:17
@AudricV AudricV force-pushed the add-content-type-and-content-length-headers-to-post-requests branch 2 times, most recently from c9b9356 to 134bc2f Compare August 24, 2022 12:38
@AudricV
Copy link
Member Author

AudricV commented Aug 24, 2022

@Stypox Could you please review again this pull request? Thank you in advance :)

AudricV and others added 5 commits November 22, 2022 11:35
Post methods in Downloader return the result of a POST request and not the one of a GET request.
This header was not sent before and was added and guessed by OkHttp. This can create issues when using other HTTP clients than OkHttp, such as Cronet.

Also make use of StandardCharsets.UTF_8 when getting bytes of bodies instead of the platform default's charset, to make sure to prevent some encoding issues on some JVMs.
This header was not sent partially before and was added and guessed by OkHttp. This can create issues when using other HTTP clients than OkHttp, such as Cronet.

Some code in the modified classes has been improved and / or deduplicated, and usages of the UTF_8 constant of the Utils class has been replaced by StandardCharsets.UTF_8 where possible.

Note that this header has been not added in except in YoutubeDashManifestCreatorsUtils, as an empty body is sent in the POST requests made by this class.
@Stypox Stypox force-pushed the add-content-type-and-content-length-headers-to-post-requests branch from 134bc2f to fec769c Compare November 22, 2022 10:44
Copy link
Member

@Stypox Stypox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AudricV I rebased and updated the YouTube mocks. The following tests fail, but I don't think they are related. You can merge this PR if you think it is still ok!

image

AudricV and others added 2 commits November 22, 2022 16:34
Not all the "learn more" button is uppercase anymore, that's only the case for
the first letter.
@AudricV AudricV force-pushed the add-content-type-and-content-length-headers-to-post-requests branch from fec769c to 34d79bd Compare November 22, 2022 16:17
@AudricV
Copy link
Member Author

AudricV commented Nov 22, 2022

@Stypox Indeed, you are almost right:

@Stypox Stypox mentioned this pull request Nov 24, 2022
3 tasks
@AudricV AudricV merged commit d5437e0 into TeamNewPipe:dev Dec 16, 2022
@AudricV AudricV deleted the add-content-type-and-content-length-headers-to-post-requests branch December 16, 2022 18:33
@opusforlife2
Copy link
Collaborator

fixed some issues on the fly

Anything worth mentioning in the blog post?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bandcamp service, https://bandcamp.com bug Issue is related to a bug youtube service, https://www.youtube.com/
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants