Skip to content

Commit 0216360

Browse files
authored
Merge pull request #934 from betatim/no-preview-on-404
[MRG] Check if nbviewer URL would show an error
2 parents 8ab31cc + c218dcb commit 0216360

File tree

2 files changed

+181
-3
lines changed

2 files changed

+181
-3
lines changed

binderhub/main.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
"""
22
Main handler classes for requests
33
"""
4+
import urllib.parse
5+
6+
from tornado.httpclient import AsyncHTTPClient, HTTPRequest
47
from tornado.web import HTTPError, authenticated
58
from tornado.httputil import url_concat
69
from tornado.log import app_log
@@ -15,6 +18,7 @@
1518
"zenodo": "Zenodo"
1619
}
1720

21+
1822
class MainHandler(BaseHandler):
1923
"""Main handler for requests"""
2024

@@ -35,7 +39,7 @@ class ParameterizedMainHandler(BaseHandler):
3539
"""Main handler that allows different parameter settings"""
3640

3741
@authenticated
38-
def get(self, provider_prefix, _unescaped_spec):
42+
async def get(self, provider_prefix, _unescaped_spec):
3943
prefix = '/v2/' + provider_prefix
4044
spec = self.get_spec_from_request(prefix)
4145
spec = spec.rstrip("/")
@@ -61,14 +65,30 @@ def get(self, provider_prefix, _unescaped_spec):
6165
org, repo_name, ref = spec.split('/', 2)
6266
# NOTE: tornado unquotes query arguments too -> notebooks%2Findex.ipynb becomes notebooks/index.ipynb
6367
filepath = self.get_argument('filepath', '').lstrip('/')
64-
68+
6569
# Check if we have a JupyterLab + file path, if so then use it for the filepath
6670
urlpath = self.get_argument('urlpath', '').lstrip('/')
6771
if urlpath.startswith("lab") and "/tree/" in urlpath:
6872
filepath = urlpath.split('tree/', 1)[-1]
69-
73+
7074
blob_or_tree = 'blob' if filepath else 'tree'
7175
nbviewer_url = f'{nbviewer_url}/{org}/{repo_name}/{blob_or_tree}/{ref}/{filepath}'
76+
77+
# Check if the nbviewer URL is valid and would display something
78+
# useful to the reader, if not we don't show it
79+
client = AsyncHTTPClient()
80+
# quote any unicode characters in the URL
81+
proto, rest = nbviewer_url.split("://")
82+
rest = urllib.parse.quote(rest)
83+
84+
request = HTTPRequest(proto + "://" + rest,
85+
method="HEAD",
86+
user_agent="BinderHub",
87+
)
88+
response = await client.fetch(request, raise_error=False)
89+
if response.code >= 400:
90+
nbviewer_url = None
91+
7292
self.render_template(
7393
"loading.html",
7494
base_url=self.settings['base_url'],
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
{
2+
"https://nbviewer.jupyter.org/github/binderhub-ci-repos/requirements/blob/20c4fe55a9b2c5011d228545e821b1c7b1723652/index.ipynb": {
3+
"body": "",
4+
"code": 200,
5+
"headers": {
6+
"Age": "0",
7+
"Backend-Name": "6Bu2TkDGiFiZ92E9Blzx2E--F_nbviewer_5_8080",
8+
"Cache-Control": "max-age=3600",
9+
"Cf-Ray": "5093d9b548ea3eae-ZRH",
10+
"Connection": "keep-alive",
11+
"Content-Encoding": "gzip",
12+
"Content-Security-Policy": "connect-src *",
13+
"Content-Type": "text/html; charset=UTF-8",
14+
"Date": "Tue, 20 Aug 2019 10:58:09 GMT",
15+
"Expect-Ct": "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"",
16+
"Server": "cloudflare",
17+
"Set-Cookie": "__cfduid=decab89505ed14fde236c5134b5feb6351566298688; expires=Wed, 19-Aug-20 10:58:08 GMT; path=/; domain=.jupyter.org; HttpOnly; Secure",
18+
"Strict-Transport-Security": "max-age=0",
19+
"Vary": "Accept-Encoding",
20+
"Via": "1.1 varnish",
21+
"X-Cache": "MISS",
22+
"X-Cache-Hits": "0",
23+
"X-Http-Reason": "OK",
24+
"X-Served-By": "cache-mxp19838-MXP",
25+
"X-Timer": "S1566298689.853803,VS0,VE860"
26+
}
27+
},
28+
"https://nbviewer.jupyter.org/github/binderhub-ci-repos/requirements/blob/master/has%20space": {
29+
"body": "",
30+
"code": 200,
31+
"headers": {
32+
"Age": "0",
33+
"Backend-Name": "6Bu2TkDGiFiZ92E9Blzx2E--F_nbviewer_5_8080",
34+
"Cache-Control": "max-age=3600",
35+
"Cf-Ray": "5093d9c5fa25cc4e-ZRH",
36+
"Connection": "keep-alive",
37+
"Content-Encoding": "gzip",
38+
"Content-Security-Policy": "connect-src *",
39+
"Content-Type": "text/html; charset=UTF-8",
40+
"Date": "Tue, 20 Aug 2019 10:58:12 GMT",
41+
"Expect-Ct": "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"",
42+
"Server": "cloudflare",
43+
"Set-Cookie": "__cfduid=dc9e56cc845755a2e6010f8e0b8b44c941566298691; expires=Wed, 19-Aug-20 10:58:11 GMT; path=/; domain=.jupyter.org; HttpOnly; Secure",
44+
"Strict-Transport-Security": "max-age=0",
45+
"Vary": "Accept-Encoding",
46+
"Via": "1.1 varnish",
47+
"X-Cache": "MISS",
48+
"X-Cache-Hits": "0",
49+
"X-Http-Reason": "OK",
50+
"X-Served-By": "cache-mxp19830-MXP",
51+
"X-Timer": "S1566298692.531481,VS0,VE476"
52+
}
53+
},
54+
"https://nbviewer.jupyter.org/github/binderhub-ci-repos/requirements/blob/master/has%20space/": {
55+
"body": "",
56+
"code": 200,
57+
"headers": {
58+
"Age": "1",
59+
"Backend-Name": "6Bu2TkDGiFiZ92E9Blzx2E--F_nbviewer_5_8080",
60+
"Cache-Control": "max-age=3600",
61+
"Cf-Ray": "5093d9cdbcfacc4a-ZRH",
62+
"Connection": "keep-alive",
63+
"Content-Encoding": "gzip",
64+
"Content-Security-Policy": "connect-src *",
65+
"Content-Type": "text/html; charset=UTF-8",
66+
"Date": "Tue, 20 Aug 2019 10:58:12 GMT",
67+
"Expect-Ct": "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"",
68+
"Server": "cloudflare",
69+
"Set-Cookie": "__cfduid=d12329d68d324ca872ee91246139e71e61566298692; expires=Wed, 19-Aug-20 10:58:12 GMT; path=/; domain=.jupyter.org; HttpOnly; Secure",
70+
"Strict-Transport-Security": "max-age=0",
71+
"Vary": "Accept-Encoding",
72+
"Via": "1.1 varnish",
73+
"X-Cache": "HIT",
74+
"X-Cache-Hits": "1",
75+
"X-Http-Reason": "OK",
76+
"X-Served-By": "cache-mxp19840-MXP",
77+
"X-Timer": "S1566298693.754207,VS0,VE1"
78+
}
79+
},
80+
"https://nbviewer.jupyter.org/github/binderhub-ci-repos/requirements/blob/master/has%20space/%C3%BCnicode.ipynb": {
81+
"body": "",
82+
"code": 200,
83+
"headers": {
84+
"Age": "0",
85+
"Backend-Name": "6Bu2TkDGiFiZ92E9Blzx2E--F_nbviewer_5_8081",
86+
"Cache-Control": "max-age=3600",
87+
"Cf-Ray": "5093d9cfca26cc5a-ZRH",
88+
"Connection": "keep-alive",
89+
"Content-Encoding": "gzip",
90+
"Content-Security-Policy": "connect-src *",
91+
"Content-Type": "text/html; charset=UTF-8",
92+
"Date": "Tue, 20 Aug 2019 10:58:14 GMT",
93+
"Expect-Ct": "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"",
94+
"Server": "cloudflare",
95+
"Set-Cookie": "__cfduid=d7639818daab3671d8e781427566c5f571566298693; expires=Wed, 19-Aug-20 10:58:13 GMT; path=/; domain=.jupyter.org; HttpOnly; Secure",
96+
"Strict-Transport-Security": "max-age=0",
97+
"Vary": "Accept-Encoding",
98+
"Via": "1.1 varnish",
99+
"X-Cache": "MISS",
100+
"X-Cache-Hits": "0",
101+
"X-Http-Reason": "OK",
102+
"X-Served-By": "cache-mxp19820-MXP",
103+
"X-Timer": "S1566298693.086667,VS0,VE1036"
104+
}
105+
},
106+
"https://nbviewer.jupyter.org/github/binderhub-ci-repos/requirements/tree/20c4fe55a9b2c5011d228545e821b1c7b1723652/": {
107+
"body": "",
108+
"code": 200,
109+
"headers": {
110+
"Age": "0",
111+
"Backend-Name": "6Bu2TkDGiFiZ92E9Blzx2E--F_nbviewer_6_8081",
112+
"Cache-Control": "max-age=3600",
113+
"Cf-Ray": "5093d9bd0a9acc42-ZRH",
114+
"Connection": "keep-alive",
115+
"Content-Encoding": "gzip",
116+
"Content-Security-Policy": "connect-src *",
117+
"Content-Type": "text/html; charset=UTF-8",
118+
"Date": "Tue, 20 Aug 2019 10:58:10 GMT",
119+
"Expect-Ct": "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"",
120+
"Server": "cloudflare",
121+
"Set-Cookie": "__cfduid=da2fed3631174e4c0eade17a81f51ad361566298690; expires=Wed, 19-Aug-20 10:58:10 GMT; path=/; domain=.jupyter.org; HttpOnly; Secure",
122+
"Strict-Transport-Security": "max-age=0",
123+
"Vary": "Accept-Encoding",
124+
"Via": "1.1 varnish",
125+
"X-Cache": "MISS",
126+
"X-Cache-Hits": "0",
127+
"X-Http-Reason": "OK",
128+
"X-Served-By": "cache-mxp19820-MXP",
129+
"X-Timer": "S1566298690.103812,VS0,VE646"
130+
}
131+
},
132+
"https://nbviewer.jupyter.org/github/binderhub-ci-repos/requirements/tree/master/": {
133+
"body": "",
134+
"code": 200,
135+
"headers": {
136+
"Age": "0",
137+
"Backend-Name": "6Bu2TkDGiFiZ92E9Blzx2E--F_nbviewer_6_8081",
138+
"Cache-Control": "max-age=3600",
139+
"Cf-Ray": "5093d9b37a33cc5a-ZRH",
140+
"Connection": "keep-alive",
141+
"Content-Encoding": "gzip",
142+
"Content-Security-Policy": "connect-src *",
143+
"Content-Type": "text/html; charset=UTF-8",
144+
"Date": "Tue, 20 Aug 2019 10:58:08 GMT",
145+
"Expect-Ct": "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"",
146+
"Server": "cloudflare",
147+
"Set-Cookie": "__cfduid=d245476acfb7b259d430a07c09c8c3ccd1566298688; expires=Wed, 19-Aug-20 10:58:08 GMT; path=/; domain=.jupyter.org; HttpOnly; Secure",
148+
"Strict-Transport-Security": "max-age=0",
149+
"Vary": "Accept-Encoding",
150+
"Via": "1.1 varnish",
151+
"X-Cache": "HIT",
152+
"X-Cache-Hits": "1",
153+
"X-Http-Reason": "OK",
154+
"X-Served-By": "cache-mxp19846-MXP",
155+
"X-Timer": "S1566298689.577043,VS0,VE1"
156+
}
157+
}
158+
}

0 commit comments

Comments
 (0)