Skip to content

Commit

Permalink
[feature/ISSUE-66] Add proxy support
Browse files Browse the repository at this point in the history
  • Loading branch information
azihassan committed Apr 5, 2024
1 parent e943fd5 commit bcb7dd4
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 15 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ jobs:
tar -xf libcurl-7.68.0-WinSSL-zlib-x86-x64.zip
xcopy dmd2\windows\bin64\libcurl.dll .
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.x'

- name: Install mitmproxy
run: pip install mitmproxy

- name: e2e tests
run: ${{ matrix.os.command }}

2 changes: 2 additions & 0 deletions script.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def request(flow):
print(flow.request.url)
12 changes: 9 additions & 3 deletions source/app.d
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ void main(string[] args)
bool noProgress;
bool noCache;
bool dethrottle = true;
string proxy;

version(linux)
{
Expand All @@ -56,6 +57,7 @@ void main(string[] args)
"no-cache", "Skip caching of HTML and base.js", &noCache,
"d|dethrottle", "Attempt to dethrottle download speed by solving the N challenge (defaults to true)", &dethrottle,
"no-dethrottle", "Skip N-challenge dethrottling attempt", () { dethrottle = false; },
"proxy", "Specifies a proxy in the type://host:port format", &proxy
);

if(help.helpWanted || args.length == 1)
Expand Down Expand Up @@ -85,7 +87,8 @@ void main(string[] args)
parallel,
noProgress,
retry > 0 ? true : noCache, //force cache refresh on failure,
dethrottle
dethrottle,
proxy
);
break;
}
Expand All @@ -105,10 +108,12 @@ void main(string[] args)
}
}

void handleURL(string url, int itag, StdoutLogger logger, bool displayFormats, bool outputURL, bool parallel, bool noProgress, bool noCache, bool dethrottle)
void handleURL(string url, int itag, StdoutLogger logger, bool displayFormats, bool outputURL, bool parallel, bool noProgress, bool noCache, bool dethrottle, string proxy)
{
logger.display(formatTitle("Handling " ~ url));
YoutubeVideoURLExtractor parser = Cache(logger, noCache ? Yes.forceRefresh : No.forceRefresh).makeParser(url, itag);
Cache cache = Cache(logger, noCache ? Yes.forceRefresh : No.forceRefresh);
cache.proxy = proxy;
YoutubeVideoURLExtractor parser = cache.makeParser(url, itag);
logger.displayVerbose("Downloaded video HTML");
logger.displayVerbose("Attempt to dethrottle : " ~ (dethrottle ? "Yes" : "No"));

Expand Down Expand Up @@ -171,5 +176,6 @@ void handleURL(string url, int itag, StdoutLogger logger, bool displayFormats, b
return 0;
}, !noProgress);
}
downloader.setProxy(proxy);
downloader.download(destination, link, url);
}
6 changes: 6 additions & 0 deletions source/cache.d
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ struct Cache
private string delegate(string url) downloadAsString;
private Flag!"forceRefresh" forceRefresh;
string cacheDirectory;
string proxy;

this(StdoutLogger logger, Flag!"forceRefresh" forceRefresh = No.forceRefresh)
{
Expand All @@ -34,6 +35,11 @@ struct Cache
curl.set(CurlOption.url, url);
curl.set(CurlOption.encoding, "deflate, gzip");
curl.set(CurlOption.followlocation, true);
curl.set(CurlOption.followlocation, true);
if(proxy)
{
curl.set(CurlOption.proxy, proxy);
}

curl.onReceive = (ubyte[] chunk) {
result ~= chunk.map!(to!(const(char))).to!string;
Expand Down
26 changes: 24 additions & 2 deletions source/downloaders.d
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ import parsers : YoutubeFormat;
interface Downloader
{
void download(string destination, string url, string referer);
Downloader setProxy(string proxy);
}

class RegularDownloader : Downloader
{
private StdoutLogger logger;
private int delegate(ulong length, ulong currentLength) onProgress;
private bool progress;
private string proxy;

this(StdoutLogger logger, int delegate(ulong length, ulong currentLength) onProgress, bool progress = true)
{
Expand All @@ -28,6 +30,12 @@ class RegularDownloader : Downloader
this.progress = progress;
}

public Downloader setProxy(string proxy)
{
this.proxy = proxy;
return this;
}

public void download(string destination, string url, string referer)
{
auto http = Curl();
Expand Down Expand Up @@ -56,6 +64,10 @@ class RegularDownloader : Downloader
http.set(CurlOption.timeout, 60 * 3);
http.set(CurlOption.connecttimeout, 60 * 3);
http.set(CurlOption.nosignal, true);
if(proxy != "")
{
http.set(CurlOption.proxy, proxy);
}

http.onReceiveHeader = (in char[] header) {
logger.displayVerbose(header);
Expand Down Expand Up @@ -83,6 +95,7 @@ class ParallelDownloader : Downloader
private string title;
private YoutubeFormat youtubeFormat;
private bool progress;
private string proxy;

this(StdoutLogger logger, string id, string title, YoutubeFormat youtubeFormat, bool progress = true)
{
Expand All @@ -93,6 +106,13 @@ class ParallelDownloader : Downloader
this.progress = progress;
}

public Downloader setProxy(string proxy)
{
this.proxy = proxy;
return this;
}


public void download(string destination, string url, string referer)
{
ulong length = url.getContentLength();
Expand All @@ -119,7 +139,7 @@ class ParallelDownloader : Downloader
logger.displayVerbose(partialDestination, " already has ", partialDestination.getSize(), " bytes, skipping");
continue;
}
new RegularDownloader(logger, (ulong _, ulong __) {
auto downloader = new RegularDownloader(logger, (ulong _, ulong __) {
if(length == 0)
{
return 0;
Expand All @@ -128,7 +148,9 @@ class ParallelDownloader : Downloader
auto percentage = 100.0 * (cast(float)(current) / length);
writef!"\r[%.2f %%] %.2f / %.2f MB"(percentage, current / 1024.0 / 1024.0, length / 1024.0 / 1024.0);
return 0;
}, progress).download(partialDestination, partialLink, url);
}, progress);
downloader.proxy = proxy;
downloader.download(partialDestination, partialLink, url);
}

writeln();
Expand Down
6 changes: 0 additions & 6 deletions source/parsers.d
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import std.json;
import std.net.curl : get;
import std.uri : decodeComponent, encodeComponent;
import std.stdio;
import std.typecons : tuple, Tuple;
Expand Down Expand Up @@ -356,11 +355,6 @@ unittest
assert(extractor.getURL(396) == "https://rr2---sn-f5o5-jhod.googlevideo.com/videoplayback?expire=1677997809&ei=keIDZIHQKMWC1ga62YWIDQ&ip=105.66.0.249&id=o-ADmt4SY6m6445pG7f4G5f72y1NE48ZiWiqWDA9pi6iQo&itag=396&aitags=133%2C134%2C135%2C136%2C137%2C160%2C242%2C243%2C244%2C247%2C248%2C278%2C394%2C395%2C396%2C397%2C398%2C399&source=youtube&requiressl=yes&mh=7c&mm=31%2C29&mn=sn-f5o5-jhod%2Csn-h5q7knes&ms=au%2Crdu&mv=m&mvi=2&pl=24&initcwndbps=275000&vprv=1&mime=video%2Fmp4&ns=V1YGXTHGUU0a4PsRJqmYKX0L&gir=yes&clen=5953258&dur=212.040&lmt=1674230525337110&mt=1677975897&fvip=4&keepalive=yes&fexp=24007246&c=WEB&txp=4537434&n=iRrA3X-4scFA5la&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRQIgE-grPIIwKVqUa_siK-FtbLtMME0LPjp9rNlzuvLN7XQCIQCfVt03aw8T9cNgG3u_pFuQafSG4AQeKpgLEHcvodbUjA%3D%3D&sig=AOq0QJ8wRQIgadIMr0vpR2qXdJuUXwsemVtnHk62MbU6kF5SrAfOGlwCIQDYj3buw7XBrdJDtAAUL42iVe5Bfi8PRLVUK3aq-Zc2iA%3D%3D");
}

YoutubeVideoURLExtractor makeParser(string html, StdoutLogger logger)
{
return makeParser(html, baseJSURL => baseJSURL.get().idup, logger);
}

YoutubeVideoURLExtractor makeParser(string html, string delegate(string) performGETRequest, StdoutLogger logger)
{
if(html.canFind("signatureCipher"))
Expand Down
34 changes: 30 additions & 4 deletions tests/tests.sh
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
set -e
chmod +x youtube-d
mitmdump -q -w proxydump & 1>/dev/null 2>/dev/null
trap "pkill -INT mitmdump" EXIT
echo Launching proxy...
sleep 2
echo Proxy running in pid $(pgrep mitmdump)

./youtube-d -p --no-progress https://www.youtube.com/watch?v=R85MK830mMo
echo Installing certificate...
curl -Lo --proxy http://localhost:8080 mitmproxy-ca-cert.pem http://mitm.it/cert/pem
mv mitmproxy-ca-cert.pem /usr/local/share/ca-certificates/mitmproxy.crt
update-ca-certificates

./youtube-d -p --no-progress --proxy http://localhost:8080 https://www.youtube.com/watch?v=R85MK830mMo

filename="Debugging Github actions-R85MK830mMo-18.mp4"
if [ ! -e "$filename" ]; then
echo "$filename not found"
exit 1
else
echo "[1/3] OK, $filename exists"
echo "[1/4] OK, $filename exists"
fi

expected_size=7079820
Expand All @@ -17,7 +27,7 @@ if [ $expected_size -ne $actual_size ]; then
echo "Wrong size. Expected $expected_size, found $actual_size"
exit 1
else
echo "[2/3] OK, size is correct"
echo "[2/4] OK, size is correct"
fi

expected_hash="e7160d310e79a5a65f382b8ca0b198dd"
Expand All @@ -26,5 +36,21 @@ if [ $expected_hash != $actual_hash ]; then
echo "Wrong hash. Expected $expected_hash, found $actual_hash"
exit 1
else
echo "[3/3] OK, md5sum is correct"
echo "[3/4] OK, md5sum is correct"
fi

urls=$(mitmdump -q -nr proxydump -s script.py)

#if [[ $urls =~ "https://www.youtube.com/watch?v=R85MK830mMo" -a $urls =~ "base.js$" -a $urls =~ "googlevideo.com" ]]; then
for url in 'https://www.youtube.com/watch?v=R85MK830mMo' 'base.js' 'googlevideo.com';
do
if echo $urls | grep -q $url
then
echo "\t[OK] $url"
else
echo "[4/4] Missing URL in proxy dump:"
echo $url
exit 1
fi
done
echo "[4/4] OK, proxying worked as expected"

0 comments on commit bcb7dd4

Please sign in to comment.