Origins and Cross-Site Requests · practice
Origins and Sites
Open mini_browser.py. Near the top are a few constants and three supplied helpers that Chapter 9 needs. Below them are the rules, and each one still only raises NotImplementedError. Run the file in the
python mini_browser.py
Each page below is compared with https://reading.example.
The last column: does the session cookie go along when the page posts a form to the reading list?
page site same origin same site cookie sent
https://reading.example not written yet not written yet not written yet not written yet
https://app.reading.example not written yet not written yet not written yet not written yet
https://notes.reading.example not written yet not written yet not written yet not written yet
https://other.example not written yet not written yet not written yet not written yet
One row per name, and nothing in it yet. This lesson fills three of the four columns.
The origin as text
Lesson 1 defined an origin_of(url) returns it as text, always in the same form, so that two origins can be compared with ==:
the scheme, then
://, then the host:https://reading.examplethen
:and the port, unless the port is the default of the scheme:http://reading.example:8080
urlsplit(url) gives you the pieces. parts.scheme and parts.hostname come back in lower case, so HTTPS://Reading.Example needs no extra work. parts.port is a number, or None when the DEFAULT_PORTS holds 80 for "http" and 443 for "https". A port that is None or equal to the default is left out of the text. Any other port is kept.
The model knows http and https URLs that have a host, and nothing else. For ftp://reading.example/x, the scheme is not a key of DEFAULT_PORTS. For a bare path such as /books, parts.hostname is None. In both cases origin_of raises
same_origin(a, b) takes two URLs and says whether their origins are equal.
A site is coarser
Three of the four names belong together: reading.example, app.reading.example, and notes.reading.example. The origin does not show that. Three hosts are three origins.
SameSite flag you set in Chapter 4 compares sites.
A site is the scheme plus the registrable domain: the part of a host name that someone registered, such as reading.example. A real browser finds that part with the public suffix co.uk and github.io are such suffixes, so the registrable domain of shop.example.co.uk is example.co.uk, three labels long.
The model has no such list, and its rule is a model rule: every name in this course ends in a suffix of one label, so the site is the scheme plus the last two labels of the host.
site https://reading.example
+----------------------------------------+
| origin https://reading.example |
| origin https://app.reading.example |
| origin https://notes.reading.example |
+----------------------------------------+
site https://other.example
+----------------------------------------+
| origin https://other.example |
+----------------------------------------+
The three hosts that end in reading.example are three origins inside one site, https://reading.example. https://other.example is one origin, and it is a site of its own.
https://reading.example, https://app.reading.example, and https://notes.reading.example are
The scheme is part of a site, as it is part of an origin. A page that came over plain http does not belong to the site of the https pages on the same host. That is the standard’s rule, and Chromium applies it to cookies. Firefox and Safari still treat the two as one site when they decide whether a SameSite cookie goes along. Lesson 3 lists this with the other differences.
Are http://reading.example and https://reading.example the same site?
Why would the two-label rule be wrong for shop.example.co.uk?
The rule has a second limit. A host that is an
What a site ignores
A site has no port. https://reading.example:8443 and https://reading.example are two origins, because the ports differ, and one site. So site_of starts from the host name alone: split parts.hostname at the dots, keep the last two labels with labels[-2:], and join them with "." again. Put the scheme and :// in front.
With the four functions written, what does this line print?
print(site_of("https://app.reading.example:8443/x"), same_site("https://notes.reading.example", "https://reading.example"), same_origin("https://notes.reading.example", "https://reading.example"))
Your task
In mini_browser.py, write the four # Write this function in Lesson 2.:
origin_of(url)returns the origin as text, and raisesValueErrorfor a URL the model does not know.same_origin(a, b)compares the origins of two URLs.site_of(url)returns the site as text: the scheme,://, and the last two labels of the host.same_site(a, b)compares the sites of two URLs.
Each function keeps its name, its raise line with your code. site_of and the two same_ functions can each call a function you wrote just before.
Then run python mini_browser.py again:
page site same origin same site cookie sent
https://reading.example https://reading.example True True not written yet
https://app.reading.example https://reading.example False True not written yet
https://notes.reading.example https://reading.example False True not written yet
https://other.example https://other.example False False not written yet
Read the two middle columns from top to bottom. Only the reading list shares an origin with itself. Its two neighbors are other origins on the same site, and other.example is neither. That difference between the second and the third column is what the rest of this chapter is about.
Then press Check my work. The last column waits for Lesson 3, which decides when a cookie goes along.
Task
Write the first four rules of the model, in mini_browser.py.
origin_of(url) returns the ://, the host in lower case, and then : and the http, 443 for https). The path and the query are dropped.
origin_of("HTTPS://Reading.Example:443/books?x=1")returns"https://reading.example".origin_of("http://reading.example:8080/a")returns"http://reading.example:8080".
It raises http or https URL with a host, such as "ftp://reading.example/x" or "/books".
site_of(url) returns the site of a URL as text: the scheme, ://, and the last two labels of the host. A site has no port.
site_of("https://notes.reading.example/page")returns"https://reading.example".site_of("http://reading.example:8080")returns"http://reading.example".
same_origin(a, b) and same_site(a, b) each take two URLs and return True or False: whether the two have the same origin, and whether they have the same site.
Run python mini_browser.py and read the table.
Then press Check my work. It calls the four origin_of must refuse with ValueError; hosts of two, three, and five labels; and pairs that differ only in the scheme, only in the port, or only in one label. It never passes an