18
18
from django .utils .deprecation import MiddlewareMixin
19
19
20
20
from readthedocs .core .unresolver import (
21
- DomainSourceType ,
22
21
InvalidCustomDomainError ,
23
22
InvalidExternalDomainError ,
24
23
InvalidSubdomainError ,
@@ -75,17 +74,13 @@ def add_proxito_headers(self, request, response):
75
74
if cache_tags :
76
75
response ['Cache-Tag' ] = ',' .join (cache_tags )
77
76
78
- if hasattr (request , 'rtdheader' ):
79
- response ['X-RTD-Project-Method' ] = 'rtdheader'
80
- elif hasattr (request , 'subdomain' ):
81
- response ['X-RTD-Project-Method' ] = 'subdomain'
82
- elif hasattr (request , 'cname' ):
83
- response ['X-RTD-Project-Method' ] = 'cname'
84
-
85
- if hasattr (request , 'external_domain' ):
86
- response ['X-RTD-Version-Method' ] = 'domain'
87
- else :
88
- response ['X-RTD-Version-Method' ] = 'path'
77
+ unresolved_domain = request .unresolved_domain
78
+ if unresolved_domain :
79
+ response ["X-RTD-Project-Method" ] = unresolved_domain .source .name
80
+ if unresolved_domain .is_from_external_domain :
81
+ response ["X-RTD-Version-Method" ] = "domain"
82
+ else :
83
+ response ["X-RTD-Version-Method" ] = "path"
89
84
90
85
def add_user_headers (self , request , response ):
91
86
"""
@@ -94,19 +89,21 @@ def add_user_headers(self, request, response):
94
89
The headers added come from ``projects.models.HTTPHeader`` associated
95
90
with the ``Domain`` object.
96
91
"""
97
- if hasattr (request , 'domain' ):
92
+ unresolved_domain = request .unresolved_domain
93
+ if unresolved_domain and unresolved_domain .is_from_custom_domain :
98
94
response_headers = [header .lower () for header in response .headers .keys ()]
99
- for http_header in request .domain .http_headers .all ():
95
+ domain = unresolved_domain .domain
96
+ for http_header in domain .http_headers .all ():
100
97
if http_header .name .lower () in response_headers :
101
98
log .error (
102
99
'Overriding an existing response HTTP header.' ,
103
100
http_header = http_header .name ,
104
- domain = request . domain .domain ,
101
+ domain = domain .domain ,
105
102
)
106
103
log .info (
107
104
'Adding custom response HTTP header.' ,
108
105
http_header = http_header .name ,
109
- domain = request . domain .domain ,
106
+ domain = domain .domain ,
110
107
)
111
108
112
109
if http_header .only_if_secure_request and not request .is_secure ():
@@ -129,17 +126,20 @@ def add_hsts_headers(self, request, response):
129
126
# Only set the HSTS header if the request is over HTTPS
130
127
return response
131
128
132
- host = request .get_host ().lower ().split (':' )[0 ]
133
- public_domain = settings .PUBLIC_DOMAIN .lower ().split (':' )[0 ]
134
129
hsts_header_values = []
135
- if settings .PUBLIC_DOMAIN_USES_HTTPS and public_domain in host :
130
+ unresolved_domain = request .unresolved_domain
131
+ if (
132
+ settings .PUBLIC_DOMAIN_USES_HTTPS
133
+ and unresolved_domain
134
+ and unresolved_domain .is_from_public_domain
135
+ ):
136
136
hsts_header_values = [
137
137
'max-age=31536000' ,
138
138
'includeSubDomains' ,
139
139
'preload' ,
140
140
]
141
- elif hasattr ( request , 'domain' ) :
142
- domain = request .domain
141
+ elif unresolved_domain and unresolved_domain . is_from_custom_domain :
142
+ domain = unresolved_domain .domain
143
143
# TODO: migrate Domains with HSTS set using these fields to
144
144
# ``HTTPHeader`` and remove this chunk of code from here.
145
145
if domain .hsts_max_age :
@@ -169,10 +169,11 @@ def add_cache_headers(self, request, response):
169
169
See https://developers.cloudflare.com/cache/about/cdn-cache-control.
170
170
"""
171
171
header = "CDN-Cache-Control"
172
+ unresolved_domain = request .unresolved_domain
172
173
# Never trust projects resolving from the X-RTD-Slug header,
173
174
# we don't want to cache their content on domains from other
174
175
# projects, see GHSA-mp38-vprc-7hf5.
175
- if hasattr ( request , "rtdheader" ) :
176
+ if unresolved_domain and unresolved_domain . is_from_http_header :
176
177
response .headers [header ] = "private"
177
178
178
179
if settings .ALLOW_PRIVATE_REPOS :
@@ -183,32 +184,18 @@ def _set_request_attributes(self, request, unresolved_domain):
183
184
"""
184
185
Set attributes in the request from the unresolved domain.
185
186
186
- - If the project was extracted from the ``X-RTD-Slug`` header,
187
- we set ``request.rtdheader`` to `True`.
188
- - If the project was extracted from the public domain,
189
- we set ``request.subdomain`` to `True`.
190
- - If the project was extracted from a custom domain,
191
- we set ``request.cname`` to `True`.
187
+ - Set ``request.unresolved_domain`` to the unresolved domain.
192
188
- If the domain needs to redirect, set the canonicalize attribute accordingly.
193
189
"""
194
- # TODO: Set the unresolved domain in the request instead of each of these attributes.
195
- source = unresolved_domain .source
190
+ request .unresolved_domain = unresolved_domain
196
191
project = unresolved_domain .project
197
- if source == DomainSourceType .http_header :
198
- request .rtdheader = True
199
- elif source == DomainSourceType .custom_domain :
192
+ if unresolved_domain .is_from_custom_domain :
200
193
domain = unresolved_domain .domain
201
- request .cname = True
202
- request .domain = domain
203
194
if domain .https and not request .is_secure ():
204
195
# Redirect HTTP -> HTTPS (302) for this custom domain.
205
196
log .debug ("Proxito CNAME HTTPS Redirect." , domain = domain .domain )
206
197
request .canonicalize = constants .REDIRECT_HTTPS
207
- elif source == DomainSourceType .external_domain :
208
- request .external_domain = True
209
- request .host_version_slug = unresolved_domain .external_version_slug
210
- elif source == DomainSourceType .public_domain :
211
- request .subdomain = True
198
+ elif unresolved_domain .is_from_public_domain :
212
199
canonical_domain = (
213
200
Domain .objects .filter (project = project )
214
201
.filter (canonical = True , https = True )
@@ -226,10 +213,11 @@ def _set_request_attributes(self, request, unresolved_domain):
226
213
project_slug = project .slug ,
227
214
)
228
215
request .canonicalize = constants .REDIRECT_SUBPROJECT_MAIN_DOMAIN
229
- else :
230
- raise NotImplementedError
231
216
232
217
def process_request (self , request ): # noqa
218
+ # Initialize our custom request attributes.
219
+ request .unresolved_domain = None
220
+
233
221
skip = any (
234
222
request .path .startswith (reverse (view ))
235
223
for view in self .skip_views
@@ -292,9 +280,6 @@ def process_request(self, request): # noqa
292
280
project_slug = project .slug ,
293
281
)
294
282
295
- # Otherwise set the slug on the request
296
- request .host_project_slug = request .slug = project .slug
297
-
298
283
# This is hacky because Django wants a module for the URLConf,
299
284
# instead of also accepting string
300
285
if project .urlconf :
0 commit comments