Skip to content

Allow sending cookies on XMLHttpRequest.send() #44

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

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 36 additions & 1 deletion pyodide_http/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,42 @@
except ImportError:
_SHOULD_PATCH = False

__version__ = "0.2.2"
from contextlib import ContextDecorator
from dataclasses import dataclass


__version__ = "0.2.3"


@dataclass
class Options:
with_credentials: bool = False


_options = Options()


def set_with_credentials_option(value: bool):
global _options
_options.with_credentials = value


class option_context(ContextDecorator):
def __init__(self, with_credentials=False):
self._with_credentials = with_credentials
self._default_options = None

def __enter__(self):
global _options
self._default_options = _options

_options = Options()
_options.with_credentials = self._with_credentials

def __exit__(self, *_):
if self._default_options is not None:
global _options
_options = self._default_options


def patch_requests(continue_on_import_error: bool = False):
Expand Down
3 changes: 3 additions & 0 deletions pyodide_http/_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
from email.parser import Parser
from pyodide.ffi import to_js

from . import _options

# need to import streaming here so that the web-worker is setup
from ._streaming import send_streaming_request

Expand Down Expand Up @@ -123,6 +125,7 @@ def send(request: Request, stream: bool = False) -> Response:
if hasattr(body, 'read'):
body = body.read()

xhr.withCredentials = _options.with_credentials
xhr.send(to_js(body))

headers = dict(Parser().parsestr(xhr.getAllResponseHeaders()))
Expand Down
24 changes: 13 additions & 11 deletions setup_test_env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,27 @@ set -e


# install chrome
wget -nc https://dl-ssl.google.com/linux/linux_signing_key.pub
cat linux_signing_key.pub | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/linux_signing_key.gpg >/dev/null
sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/chrome.list'
sudo apt update
sudo apt install google-chrome-stable
wget -nc https://dl-ssl.google.com/linux/linux_signing_key.pub
cat linux_signing_key.pub | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/linux_signing_key.gpg >/dev/null
sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/chrome.list'
sudo apt update
sudo apt install google-chrome-stable


# pyodide build and test
pip install pytest
pip install pyodide-build pytest-pyodide
pip install pytest
pip install pyodide-build pytest-pyodide
# install chromedriver stuff for selenium to control chrome
pip install selenium webdriver-manager
pip install selenium webdriver-manager
pip install chromedriver-binary-auto
# make sure chromedriver is on path
export PATH=$PATH:`chromedriver-path`

# run the tests
cd tests
# get pyodide to tests/pyodide
wget https://github.com/pyodide/pyodide/releases/download/0.21.0/pyodide-build-0.21.0.tar.bz2
tar xjf pyodide-build-0.21.0.tar.bz2
pytest . --dist-dir ./pyodide --rt chrome -v
wget https://github.com/pyodide/pyodide/releases/download/0.25.1/pyodide-0.25.1.tar.bz2
tar xjf pyodide-0.25.1.tar.bz2
cp "$(python3 -c 'import os.path; import pytest_pyodide; print(os.path.dirname(pytest_pyodide.__file__))')/_templates/test.html" pyodide/
cp "$(python3 -c 'import os.path; import pytest_pyodide; print(os.path.dirname(pytest_pyodide.__file__))')/_templates/webworker_dev.js" pyodide/
pytest . --dist-dir ./pyodide --rt chrome -v
4 changes: 2 additions & 2 deletions tests/pyodide_worker.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
importScripts("https://cdn.jsdelivr.net/pyodide/v0.21.3/full/pyodide.js");
importScripts("https://cdn.jsdelivr.net/pyodide/v0.25.1/full/pyodide.js");

onmessage = async function (e) {
try {
Expand All @@ -25,4 +25,4 @@ onmessage = async function (e) {
// if you prefer onerror events
// setTimeout(() => { throw err; });
}
};
};
83 changes: 79 additions & 4 deletions tests/test_non_streaming.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from pathlib import Path
import os.path
import glob

from pytest_pyodide import run_in_pyodide, spawn_web_server
from pytest import fixture
from pytest import fixture, fail


@fixture(scope="module")
Expand Down Expand Up @@ -43,28 +44,99 @@ def _install_package(selenium, base_url):
import requests
"""
)
break
else:
fail(f"no pre-built *.whl found in {os.path.relpath(wheel_folder)}")


def test_install_package(selenium_standalone, web_server_base):
_install_package(selenium_standalone, web_server_base)


def test_credentials_context_manager(selenium_standalone, dist_dir, web_server_base):
_install_package(selenium_standalone, web_server_base)

@run_in_pyodide
def test_fn(selenium_standalone, base_url):
import pyodide_http as ph

assert not ph._options.with_credentials

with ph.option_context(with_credentials=True):
assert ph._options.with_credentials

assert not ph._options.with_credentials


def test_credentials_option(selenium_standalone, dist_dir, web_server_base):
_install_package(selenium_standalone, web_server_base)

@run_in_pyodide
def test_fn(selenium_standalone, base_url):
import pyodide_http as ph

assert not ph._options.with_credentials

ph.set_with_credentials_option(True)
assert ph._options.with_credentials

ph.set_with_credentials_option(False)
assert not ph._options.with_credentials


def test_requests_get(selenium_standalone, dist_dir, web_server_base):
_install_package(selenium_standalone, web_server_base)

@run_in_pyodide
def test_fn(selenium_standalone, base_url):
import requests

import pyodide_http._requests
assert pyodide_http._requests._IS_PATCHED

import pyodide_http as ph

print("get:", base_url)
url = f"{base_url}/yt-4.0.4-cp310-cp310-emscripten_3_1_14_wasm32.whl"
resp = requests.get(url)
url = f"{base_url}/yt-4.1.4-cp311-cp311-emscripten_3_1_46_wasm32.whl"

# The test web server sets "Access-Control-Allow-Origin: *" which disallows sending credentials.
# Credentials are explicitly disabled, although that's the default, to exercise the option code.
with ph.option_context(with_credentials=False):
resp = requests.get(url)

data = resp.content
assert resp.request.url == url

return len(data)

assert test_fn(selenium_standalone, f"{web_server_base}{dist_dir}/") == 11373926
assert test_fn(selenium_standalone, f"{web_server_base}{dist_dir}/") == 78336150


def test_urllib_get(selenium_standalone, dist_dir, web_server_base):
_install_package(selenium_standalone, web_server_base)

@run_in_pyodide
def test_fn(selenium_standalone, base_url):
import urllib.request

import pyodide_http._urllib
assert pyodide_http._urllib._IS_PATCHED

import pyodide_http as ph

# The test web server sets "Access-Control-Allow-Origin: *" which disallows sending credentials.
# Credentials are explicitly disabled, although that's the default, to exercise the option code.
ph.set_with_credentials_option(False)

print("get:", base_url)
url = f"{base_url}/yt-4.1.4-cp311-cp311-emscripten_3_1_46_wasm32.whl"
with urllib.request.urlopen(url) as resp:
data = resp.read()
assert resp.url == url

return len(data)

assert test_fn(selenium_standalone, f"{web_server_base}{dist_dir}/") == 78336150


def test_requests_404(selenium_standalone, dist_dir, web_server_base):
Expand All @@ -74,6 +146,9 @@ def test_requests_404(selenium_standalone, dist_dir, web_server_base):
def test_fn(selenium_standalone, base_url):
import requests

import pyodide_http._requests
assert pyodide_http._requests._IS_PATCHED

print("get:", base_url)
resp = requests.get(f"{base_url}/surely_this_file_does_not_exist.hopefully.")
response = resp.status_code
Expand Down
6 changes: 5 additions & 1 deletion tests/test_streaming.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@
import socketserver

from pathlib import Path
import os.path
import glob

import pytest_pyodide
from pytest import fixture
from pytest import fixture, fail
from pytest_pyodide import run_in_pyodide


Expand Down Expand Up @@ -160,6 +161,9 @@ def _install_package(selenium, base_url):
import requests
"""
)
break
else:
fail(f"no pre-built *.whl found in {os.path.relpath(wheel_folder)}")


def get_install_package_code(base_url):
Expand Down
Loading