Ticket #2200: twisted.web2.server.patch
| File twisted.web2.server.patch, 6.8 KB (added by Cyrus Daboo, 7 years ago) |
|---|
-
twisted/web2/server.py
1 1 # -*- test-case-name: twisted.web2.test.test_server -*- 2 2 # Copyright (c) 2001-2004 Twisted Matrix Laboratories. 3 3 # See LICENSE for details. 4 from twisted.internet.defer import succeed 5 from twisted.web2.dav.util import joinURL 4 6 5 7 6 8 """This is a web-sever which integrates with the twisted.internet … … 150 152 self._initialprepath = kw['prepathuri'] 151 153 del kw['prepathuri'] 152 154 155 self._resourcesByURL = {} 156 self._urlsByResource = {} 157 153 158 # Copy response filters from the class 154 159 self.responseFilters = self.responseFilters[:] 155 160 self.files = {} 156 161 self.resources = [] 157 162 http.Request.__init__(self, *args, **kw) 158 163 159 def addResponseFilter(self, f, atEnd=False): 164 def addResponseFilter(self, filter, atEnd=False, onlyOnce=False): 165 """ 166 Add a response filter to this request. 167 Response filters are applied to the response to this request in order. 168 @param filter: a callable which takes an response argument and returns 169 a response object. 170 @param atEnd: if C{True}, C{filter} is added at the end of the list of 171 response filters; if C{False}, it is added to the beginning. 172 @param onlyOnce: if C{True}, C{filter} is not added to the list of 173 response filters if it already in the list. 174 """ 175 if onlyOnce and filter in self.responseFilters: 176 return 160 177 if atEnd: 161 self.responseFilters.append(f )178 self.responseFilters.append(filter) 162 179 else: 163 self.responseFilters.insert(0, f )180 self.responseFilters.insert(0, filter) 164 181 165 182 def unparseURL(self, scheme=None, host=None, port=None, 166 183 path=None, params=None, querystring=None, fragment=None): … … 265 282 266 283 d = defer.Deferred() 267 284 d.addCallback(self._getChild, self.site.resource, self.postpath) 285 d.addCallback(self._rememberResource, "/" + "/".join(self.prepath)) 268 286 d.addCallback(lambda res, req: res.renderHTTP(req), self) 269 287 d.addCallback(self._cbFinishRender) 270 288 d.addErrback(self._processingFailed) … … 320 338 url = "/" + "/".join(path) 321 339 else: 322 340 url = "/" 323 324 self._rememberURLForResource(quote(url), res)325 341 return res 326 342 #else: 327 343 # raise ValueError("locateChild must not return StopTraversal with a resource other than self.") … … 342 358 self.prepath.append(self.postpath.pop(0)) 343 359 344 360 child = self._getChild(None, newres, newpath, updatepaths=updatepaths) 345 self._rememberURLForResource(quote(url), child)346 361 347 362 return child 348 363 349 _resourcesByURL = weakref.WeakKeyDictionary() 350 351 def _rememberURLForResource(self, url, resource): 364 def _rememberResource(self, resource, url): 352 365 """ 353 Remember the URL of visited resources.366 Remember the URL of a visited resources. 354 367 """ 355 368 self._resourcesByURL[resource] = url 369 self._urlsByResource[url] = resource 370 return resource 356 371 357 372 def urlForResource(self, resource): 358 373 """ … … 367 382 368 383 @return: the URL of C{resource} if known, otherwise C{None}. 369 384 """ 370 try: 371 return self._resourcesByURL[resource] 372 except KeyError: 373 return None 385 return self._resourcesByURL.get(resource, None) 374 386 375 387 def locateResource(self, url): 376 388 """ … … 385 397 The contained response will have a status code of 386 398 L{responsecode.BAD_REQUEST}. 387 399 """ 388 if url is None: return None 400 if url is None: 401 return None 389 402 403 cached = self._urlsByResource.get(url, None) 404 if cached is not None: 405 return succeed(cached) 406 390 407 # 391 408 # Parse the URL 392 409 # … … 406 423 "URL is not on this site (%s://%s/): %s" % (scheme, self.headers.getHeader("host"), url) 407 424 )) 408 425 409 segments = path.split("/")426 segments = unquote(path).split("/") 410 427 assert segments[0] == "", "URL path didn't begin with '/': %s" % (path,) 411 428 segments = segments[1:] 412 segments = map(unquote, segments)413 429 414 430 def notFound(f): 415 431 f.trap(http.HTTPError) 416 432 if f.response.code != responsecode.NOT_FOUND: 417 r aisef433 return f 418 434 return None 419 435 420 return defer.maybeDeferred(self._getChild, None, self.site.resource, segments, updatepaths=False) 436 d = defer.maybeDeferred(self._getChild, None, self.site.resource, segments, updatepaths=False) 437 d.addCallback(self._rememberResource, path) 438 d.addErrback(notFound) 439 return d 421 440 441 def locateChildResource(self, parent, child_name): 442 """ 443 Looks up the child resource with the given name given the parent 444 resource. This is similar to locateResource(), but doesn't have to 445 start the lookup from the root resource, so it is potentially faster. 446 @param parent: the parent of the resource being looked up. 447 @param child_name: the name of the child of C{parent} to looked up. 448 to C{parent}. 449 @return: a L{Deferred} resulting in the L{IResource} at the 450 given URL or C{None} if no such resource can be located. 451 @raise HTTPError: If C{url} is not a URL on the site that this 452 request is being applied to. The contained response will 453 have a status code of L{responsecode.BAD_GATEWAY}. 454 @raise HTTPError: If C{url} contains a query or fragment. 455 The contained response will have a status code of 456 L{responsecode.BAD_REQUEST}. 457 """ 458 if parent is None or child_name is None: 459 return None 460 461 url = joinURL(self.urlForResource(parent), child_name) 462 463 cached = self._urlsByResource.get(url, None) 464 if cached is not None: 465 return succeed(cached) 466 467 assert "/" not in child_name, "Child name may not contain '/': %s" % (child_name,) 468 469 segment = unquote(child_name) 470 471 def notFound(f): 472 f.trap(http.HTTPError) 473 if f.response.code != responsecode.NOT_FOUND: 474 return f 475 return None 476 477 d = defer.maybeDeferred(self._getChild, None, parent, [segment], updatepaths=False) 478 d.addCallback(self._rememberResource, url) 479 d.addErrback(notFound) 480 return d 481 422 482 def _processingFailed(self, reason): 423 483 if reason.check(http.HTTPError) is not None: 424 484 # If the exception was an HTTPError, leave it alone
