def report_DAV__principal_search_property_set(self, request, principal_search_property_set): """ Generate a principal-search-property-set REPORT. (RFC 3744, section 9.5) """ # Verify root element if not isinstance(principal_search_property_set, davxml.PrincipalSearchPropertySet): raise ValueError("%s expected as root element, not %s." % (davxml.PrincipalSearchPropertySet.sname(), principal_search_property_set.sname())) # Only handle Depth: 0 depth = request.headers.getHeader("depth", "0") if depth != "0": log.error( "Error in principal-search-property-set REPORT, Depth set to %s" % (depth, )) raise HTTPError( StatusResponse(responsecode.BAD_REQUEST, "Depth %s not allowed" % (depth, ))) # Get details from the resource result = self.principalSearchPropertySet() if result is None: log.error( "Error in principal-search-property-set REPORT not supported on: %s" % (self, )) raise HTTPError( StatusResponse(responsecode.BAD_REQUEST, "Not allowed on this resource")) yield Response(code=responsecode.OK, stream=MemoryStream(result.toxml()))
def http_GET(self, request): """ The iSchedule GET method. """ if not request.args or self._podding: # Do normal GET behavior return self.render(request) action = request.args.get("action", ("", )) if len(action) != 1: raise HTTPError( StatusResponse( responsecode.BAD_REQUEST, "Invalid action parameter", )) action = action[0] action = { "capabilities": self.doCapabilities, }.get(action, None) if action is None: raise HTTPError( StatusResponse( responsecode.BAD_REQUEST, "Unknown action action parameter", )) return action(request)
def http_POST(self, request): """ POST method with JSON body is used for control. """ # # Check authentication and access controls # yield self.authorize(request, (davxml.Read(),)) contentType = request.headers.getHeader("content-type") # Check content first if "{}/{}".format(contentType.mediaType, contentType.mediaSubtype) != "application/json": self.log.error("MIME type {mime} not allowed in request", mime=contentType) raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, "MIME type {} not allowed in request".format(contentType))) body = (yield allDataFromStream(request.stream)) try: j = json.loads(body) except (ValueError, TypeError) as e: self.log.error("Invalid JSON data in request: {ex}\n{body}", ex=e, body=body) raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, "Invalid JSON data in request: {}\n{}".format(e, body))) try: action = j["action"] except KeyError: self._error("error", "No 'action' member in root JSON object.") method = "action_{}".format(action) if not hasattr(self, method): self._error("error", "The action '{}' is not supported.".format(action)) result = yield getattr(self, method)(j) returnValue(result)
def report_urn_ietf_params_xml_ns_caldav_free_busy_query(self, request, freebusy): """ Generate a free-busy REPORT. (CalDAV-access-09, section 7.8) """ if not self.isCollection(): log.error("freebusy report is only allowed on collection resources {s!r}", s=self) raise HTTPError(StatusResponse(responsecode.FORBIDDEN, "Not a calendar collection")) if freebusy.qname() != (caldavxml.caldav_namespace, "free-busy-query"): raise ValueError("{CalDAV:}free-busy-query expected as root element, not %s." % (freebusy.sname(),)) timerange = freebusy.timerange if not timerange.valid(): raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, "Invalid time-range specified")) fbset = [] accepted_type = bestAcceptType(request.headers.getHeader("accept"), Component.allowedTypes()) if accepted_type is None: raise HTTPError(StatusResponse(responsecode.NOT_ACCEPTABLE, "Cannot generate requested data type")) def getCalendarList(calresource, uri): # @UnusedVariable """ Store the calendars that match the query in L{fbset} which will then be used with the freebusy query. @param calresource: the L{CalDAVResource} for a calendar collection. @param uri: the uri for the calendar collection resource. """ fbset.append(calresource._newStoreObject) return succeed(True) # Run report taking depth into account depth = request.headers.getHeader("depth", "0") yield report_common.applyToCalendarCollections(self, request, request.uri, depth, getCalendarList, (caldavxml.ReadFreeBusy(),)) # Do the actual freebusy query against the set of matched calendars principal = yield self.resourceOwnerPrincipal(request) organizer = recipient = LocalCalendarUser(principal.canonicalCalendarUserAddress(), principal.record) timerange = Period(timerange.start, timerange.end) try: fbresult = yield FreebusyQuery(organizer=organizer, recipient=recipient, timerange=timerange).generateAttendeeFreeBusyResponse(fbset=fbset, method=None) except NumberOfMatchesWithinLimits: log.error("Too many matching components in free-busy report") raise HTTPError(ErrorResponse( responsecode.FORBIDDEN, davxml.NumberOfMatchesWithinLimits(), "Too many components" )) except TimeRangeLowerLimit, e: raise HTTPError(ErrorResponse( responsecode.FORBIDDEN, caldavxml.MinDateTime(), "Time-range value too far in the past. Must be on or after %s." % (str(e.limit),) ))
def _prepareForCopy(destination, destination_uri, request, depth): # # Destination must be a DAV resource # try: destination = IDAVResource(destination) except TypeError: log.error("Attempt to %s to a non-DAV resource: (%s) %s" % (request.method, destination.__class__, destination_uri)) raise HTTPError( StatusResponse( responsecode.FORBIDDEN, "Destination %s is not a WebDAV resource." % (destination_uri, ))) # # FIXME: Right now we don't know how to copy to a non-DAVFile resource. # We may need some more API in IDAVResource. # So far, we need: .exists(), .fp.parent() # if not isinstance(destination, txweb2.dav.static.DAVFile): log.error( "DAV copy between non-DAVFile DAV resources isn't implemented") raise HTTPError( StatusResponse( responsecode.NOT_IMPLEMENTED, "Destination %s is not a DAVFile resource." % (destination_uri, ))) # # Check for existing destination resource # overwrite = request.headers.getHeader("overwrite", True) if destination.exists() and not overwrite: log.error( "Attempt to %s onto existing file without overwrite flag enabled: %s" % (request.method, destination)) raise HTTPError( StatusResponse( responsecode.PRECONDITION_FAILED, "Destination %s already exists." % (destination_uri, ))) # # Make sure destination's parent exists # if not destination.parent().isCollection(): log.error("Attempt to %s to a resource with no parent: %s" % (request.method, destination.fp.path)) raise HTTPError( StatusResponse(responsecode.CONFLICT, "No parent collection.")) return destination, destination_uri, depth
def linkedResource(self, request): if not hasattr(self, "_linkedResource"): if self.linkURL in self.loopDetect: raise HTTPError(StatusResponse(responsecode.LOOP_DETECTED, "Recursive link target: %s" % (self.linkURL,))) else: self.loopDetect.add(self.linkURL) self._linkedResource = (yield request.locateResource(self.linkURL)) self.loopDetect.remove(self.linkURL) if self._linkedResource is None: raise HTTPError(StatusResponse(responsecode.NOT_FOUND, "Missing link target: %s" % (self.linkURL,))) returnValue(self._linkedResource)
def http_PROPFIND(self, request): """ Respond to a PROPFIND request. (RFC 2518, section 8.1) """ if not self.exists(): # Return 403 if parent does not allow Bind parentURL = parentForURL(request.uri) parent = (yield request.locateResource(parentURL)) yield parent.authorize(request, (davxml.Bind(), )) log.error("Resource not found: %s" % (self, )) raise HTTPError(responsecode.NOT_FOUND) # # Check authentication and access controls # yield self.authorize(request, (davxml.Read(), )) # # Read request body # try: doc = (yield davXMLFromStream(request.stream)) except ValueError, e: log.error("Error while handling PROPFIND body: %s" % (e, )) raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, str(e)))
def http_ACL(self, request): """ Respond to a ACL request. (RFC 3744, section 8.1) """ if not self.exists(): log.error("File not found: %s" % (self,)) yield responsecode.NOT_FOUND return # # Check authentication and access controls # x = waitForDeferred(self.authorize(request, (davxml.WriteACL(),))) yield x x.getResult() # # Read request body # doc = waitForDeferred(davXMLFromStream(request.stream)) yield doc try: doc = doc.getResult() except ValueError, e: log.error("Error while handling ACL body: %s" % (e,)) raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, str(e)))
def finalChecks(self): """ Final checks before doing the actual scheduling. """ # With implicit scheduling only certain types of iTIP operations are allowed for POST. if self.doingPOST: # Freebusy requests always processed if self.checkForFreeBusy(): return # COUNTER and DECLINE-COUNTER allowed if self.calendar.propertyValue("METHOD") in ("COUNTER", "DECLINECOUNTER"): return # Anything else is not allowed. However, for compatibility we will optionally # return a success response for all attendees. if config.Scheduling.CalDAV.OldDraftCompatibility: self.fakeTheResult = True else: raise HTTPError( StatusResponse( responsecode.BAD_REQUEST, "Invalid iTIP message for implicit scheduling"))
def http_MKCOL(self, request): """ Respond to a MKCOL request. (RFC 2518, section 8.3) """ parent = waitForDeferred(request.locateResource(parentForURL(request.uri))) yield parent parent = parent.getResult() x = waitForDeferred(parent.authorize(request, (davxml.Bind(), ))) yield x x.getResult() if self.exists(): log.error("Attempt to create collection where file exists: %s" % (self, )) raise HTTPError(responsecode.NOT_ALLOWED) if not parent.isCollection(): log.error( "Attempt to create collection with non-collection parent: %s" % (self, )) raise HTTPError( StatusResponse(responsecode.CONFLICT, "Parent resource is not a collection.")) # # Read request body # x = waitForDeferred(noDataFromStream(request.stream)) yield x try: x.getResult() except ValueError, e: log.error("Error while handling MKCOL body: %s" % (e, )) raise HTTPError(responsecode.UNSUPPORTED_MEDIA_TYPE)
def locateChild(self, req, segments): """ See L{IResource}C{.locateChild}. """ # If getChild() finds a child resource, return it try: child = self.getChild(segments[0]) if child is not None: return (child, segments[1:]) except InsecurePath: raise HTTPError( StatusResponse(responsecode.FORBIDDEN, "Invalid URL path")) # If we're not backed by a directory, we have no children. # But check for existance first; we might be a collection resource # that the request wants created. self.fp.restat(False) if self.fp.exists() and not self.fp.isdir(): return (None, ()) # OK, we need to return a child corresponding to the first segment path = segments[0] if path == "": # Request is for a directory (collection) resource return (self, ()) return (self.createSimilarFile(self.fp.child(path).path), segments[1:])
def __init__(self, qname): HTTPError.__init__( self, StatusResponse( responsecode.NOT_FOUND, "No such property: %s" % encodeXMLName(*qname) ) )
def setGroupMemberSet(self, new_members, request): # FIXME: as defined right now it is not possible to specify a # calendar-user-proxy group as a member of any other group since the # directory service does not know how to lookup these special resource # UIDs. # # Really, c-u-p principals should be treated the same way as any other # principal, so they should be allowed as members of groups. # # This implementation now raises an exception for any principal it # cannot find. # Break out the list into a set of URIs. members = [str(h) for h in new_members.children] # Map the URIs to principals and a set of UIDs. principals = [] newUIDs = set() for uri in members: principal = yield self.pcollection._principalForURI(uri) # Invalid principals MUST result in an error. if principal is None or principal.principalURL() != uri: raise HTTPError(StatusResponse( responsecode.BAD_REQUEST, "Attempt to use a non-existent principal %s " "as a group member of %s." % (uri, self.principalURL(),) )) principals.append(principal) newUIDs.add(principal.principalUID()) # Get the old set of expanded UIDs oldUIDs = set() oldPrincipals = yield self.groupMembers() oldUIDs.update([p.principalUID() for p in oldPrincipals]) oldPrincipals = yield self.expandedGroupMembers() oldUIDs.update([p.principalUID() for p in oldPrincipals]) # Change membership yield self.setGroupMemberSetPrincipals(principals) # Get the new set of UIDs newUIDs = set() newPrincipals = yield self.groupMembers() newUIDs.update([p.principalUID() for p in newPrincipals]) newPrincipals = yield self.expandedGroupMembers() newUIDs.update([p.principalUID() for p in newPrincipals]) # Invalidate the primary principal's cache, and any principal's whose # membership status changed yield self.parent.cacheNotifier.changed() changedUIDs = newUIDs.symmetric_difference(oldUIDs) for uid in changedUIDs: principal = yield self.pcollection.principalForUID(uid) if principal: yield principal.cacheNotifier.changed() returnValue(True)
def preconditions_PUT(self, request): # # Check authentication and access controls # if self.exists(): x = waitForDeferred(self.authorize(request, (davxml.WriteContent(), ))) yield x x.getResult() else: parent = waitForDeferred( request.locateResource(parentForURL(request.uri))) yield parent parent = parent.getResult() if not parent.exists(): raise HTTPError( StatusResponse(responsecode.CONFLICT, "cannot PUT to non-existent parent")) x = waitForDeferred(parent.authorize(request, (davxml.Bind(), ))) yield x x.getResult() # # HTTP/1.1 (RFC 2068, section 9.6) requires that we respond with a Not # Implemented error if we get a Content-* header which we don't # recognize and handle properly. # for header, _ignore_value in request.headers.getAllRawHeaders(): if header.startswith("Content-") and header not in ( # "Content-Base", # Doesn't make sense in PUT? # "Content-Encoding", # Requires that we decode it? "Content-Language", "Content-Length", # "Content-Location", # Doesn't make sense in PUT? "Content-MD5", # "Content-Range", # FIXME: Need to implement this "Content-Type", ): log.error( "Client sent unrecognized content header in PUT request: %s" % (header, )) raise HTTPError( StatusResponse( responsecode.NOT_IMPLEMENTED, "Unrecognized content header %r in request." % (header, )))
def renderHTTP(self, request): if not self.directory: raise HTTPError( StatusResponse(responsecode.SERVICE_UNAVAILABLE, "Service is starting up")) response = (yield maybeDeferred( super(DirectoryBackedAddressBookResource, self).renderHTTP, request)) returnValue(response)
def get(self, qname): try: property = self._dict[qname] except KeyError: raise HTTPError( StatusResponse( responsecode.NOT_FOUND, "No such property: %s" % (encodeXMLName(*qname), ))) doc = element.WebDAVDocument.fromString(property) return doc.root_element
class ReadOnlyWritePropertiesResourceMixIn(object): """ Read only that will allow writing of properties resource. """ readOnlyResponse = StatusResponse(responsecode.FORBIDDEN, "Resource is read only.") def _forbidden(self, request): return self.readOnlyResponse http_DELETE = _forbidden http_MOVE = _forbidden http_PUT = _forbidden
def renderHTTP(self, request): """ Do the reverse proxy request and return the response. @param request: the incoming request that needs to be proxied. @type request: L{Request} @return: Deferred L{Response} """ self.log.info("{method} {poolID}:{uri} {proto}", method=request.method, poolID=self.poolID, uri=request.uri, proto="HTTP/{}.{}".format(*request.clientproto)) # Check for multi-hop if not self.allowMultiHop: x_server = request.headers.getHeader("x-forwarded-server") if x_server: for item in x_server: if item.lower() == config.ServerHostName.lower(): self.log.error("ReverseProxy loop detected: x-forwarded-server:{xfs}", xfs=str(x_server)) raise HTTPError(StatusResponse(responsecode.BAD_GATEWAY, "Too many x-forwarded-server hops")) clientPool = getHTTPClientPool(self.poolID) proxyRequest = ClientRequest(request.method, request.uri, request.headers, request.stream) # Need x-forwarded-(for|host|server) headers. First strip any existing ones out, then add ours proxyRequest.headers.removeHeader("x-forwarded-host") proxyRequest.headers.removeHeader("x-forwarded-for") proxyRequest.headers.removeHeader("x-forwarded-server") proxyRequest.headers.addRawHeader("x-forwarded-host", request.host) proxyRequest.headers.addRawHeader("x-forwarded-for", request.remoteAddr.host) proxyRequest.headers.addRawHeader("x-forwarded-server", config.ServerHostName) try: response = yield clientPool.submitRequest(proxyRequest) except Exception as e: self.log.error("ReverseProxy failed: {exc}", exc=str(e)) raise HTTPError(StatusResponse(responsecode.BAD_GATEWAY, "Cannot connect via poolID={poolID}".format(poolID=self.poolID))) returnValue(response)
def prepareForCopy(self, request): # # Get the depth # depth = request.headers.getHeader("depth", "infinity") if depth not in ("0", "infinity"): msg = ("Client sent illegal depth header value: %s" % (depth,)) log.error(msg) raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, msg)) # # Verify this resource exists # if not self.exists(): log.error("File not found: %s" % (self,)) raise HTTPError(StatusResponse( responsecode.NOT_FOUND, "Source resource %s not found." % (request.uri,) )) # # Get the destination # destination_uri = request.headers.getHeader("destination") if not destination_uri: msg = "No destination header in %s request." % (request.method,) log.error(msg) raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, msg)) d = request.locateResource(destination_uri) d.addCallback(_prepareForCopy, destination_uri, request, depth) return d
def get(self, qname, uid=None): """ Retrieve the value of a property stored as an extended attribute on the wrapped path. @param qname: The property to retrieve as a two-tuple of namespace URI and local name. @param uid: The per-user identifier for per user properties. @raise HTTPError: If there is no value associated with the given property. @return: A L{WebDAVDocument} representing the value associated with the given property. """ try: data = self.attrs.get(self._encode(qname, uid)) except KeyError: raise HTTPError( StatusResponse( responsecode.NOT_FOUND, "No such property: %s" % (encodeXMLName(*qname), ))) except IOError, e: if e.errno in _ATTR_MISSING or e.errno == errno.ENOENT: raise HTTPError( StatusResponse( responsecode.NOT_FOUND, "No such property: %s" % (encodeXMLName(*qname), ))) else: raise HTTPError( StatusResponse( statusForFailure(Failure()), "Unable to read property: %s" % (encodeXMLName(*qname), )))
def http_REPORT(self, request): """ Respond to a REPORT request. (RFC 3253, section 3.6) """ if not self.exists(): log.error("Resource not found: %s" % (self,)) raise HTTPError(responsecode.NOT_FOUND) # # Read request body # try: doc = (yield davXMLFromStream(request.stream)) except ValueError, e: log.error("Error while handling REPORT body: {err}", err=str(e)) raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, str(e)))
def renderHTTP(self, request): try: _ignore_authnUser, authzUser = yield self.authenticate(request) except Exception: authzUser = None # Turn 404 into 401 if authzUser is None: response = (yield UnauthorizedResponse.makeResponse( request.credentialFactories, request.remoteAddr)) returnValue(response) else: response = StatusResponse(responsecode.NOT_FOUND, "Resource not found") returnValue(response)
def get(self, qname, uid=None, cache=True): if cache: propertyCache = self.propertyCache() qnameuid = qname + (uid, ) if qnameuid in propertyCache: return propertyCache[qnameuid] else: raise HTTPError( StatusResponse( responsecode.NOT_FOUND, "No such property: %s%s" % (uid if uid else "", encodeXMLName(*qname)))) self.log.debug("Read for %s%s on %s" % (("{%s}:" % (uid, )) if uid else "", qname, self.childPropertyStore.resource.fp.path)) return self.childPropertyStore.get(qname, uid=uid)
def http_MKCALENDAR(self, request): """ Respond to a MKCALENDAR request. (CalDAV-access-09, section 5.3.1) """ # # Check authentication and access controls # parent = (yield request.locateResource(parentForURL(request.uri))) yield parent.authorize(request, (davxml.Bind(), )) if self.exists(): log.error("Attempt to create collection where resource exists: %s" % (self, )) raise HTTPError( ErrorResponse( responsecode.FORBIDDEN, (davxml.dav_namespace, "resource-must-be-null"), "Resource already exists", )) if not parent.isCollection(): log.error( "Attempt to create collection with non-collection parent: %s" % (self, )) raise HTTPError( ErrorResponse( responsecode.CONFLICT, (caldavxml.caldav_namespace, "calendar-collection-location-ok"), "Cannot create calendar inside another calendar", )) # # Read request body # try: doc = (yield davXMLFromStream(request.stream)) yield self.createCalendar(request) except ValueError, e: log.error("Error while handling MKCALENDAR: %s" % (e, )) raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, str(e)))
def readProperty(self, property, request): if type(property) is tuple: qname = property else: qname = property.qname() namespace, name = qname if namespace == dav_namespace: if name == "resourcetype": rtype = self.resourceType() returnValue(rtype) elif namespace == calendarserver_namespace: if name == "expanded-group-member-set": principals = (yield self.expandedGroupMembers()) returnValue(customxml.ExpandedGroupMemberSet( *[element.HRef(p.principalURL()) for p in principals] )) elif name == "expanded-group-membership": principals = (yield self.expandedGroupMemberships()) returnValue(customxml.ExpandedGroupMembership( *[element.HRef(p.principalURL()) for p in principals] )) elif name == "record-type": if hasattr(self, "record"): returnValue( customxml.RecordType( self.record.service.recordTypeToOldName( self.record.recordType ) ) ) else: raise HTTPError(StatusResponse( responsecode.NOT_FOUND, "Property %s does not exist." % (qname,) )) result = (yield super(DAVPrincipalResource, self).readProperty(property, request)) returnValue(result)
def extractCalendarServerPrincipalSearchData(doc): """ Extract relevant info from a CalendarServerPrincipalSearch document @param doc: CalendarServerPrincipalSearch object to extract info from @return: A tuple containing: the list of tokens the context string the applyTo boolean the clientLimit integer the propElement containing the properties to return """ context = doc.attributes.get("context", None) applyTo = False tokens = [] clientLimit = None for child in doc.children: if child.qname() == (dav_namespace, "prop"): propElement = child elif child.qname() == (dav_namespace, "apply-to-principal-collection-set"): applyTo = True elif child.qname() == (calendarserver_namespace, "search-token"): tokenValue = child.toString().strip() if tokenValue: tokens.append(tokenValue) elif child.qname() == (calendarserver_namespace, "limit"): try: nresults = child.childOfType(customxml.NResults) clientLimit = int(str(nresults)) except ( TypeError, ValueError, ): msg = "Bad XML: unknown value for <limit> element" log.warn(msg) raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, msg)) return tokens, context, applyTo, clientLimit, propElement
def list(self, uid=None, filterByUID=True): """ Enumerate the property names stored in extended attributes of the wrapped path. @param uid: The per-user identifier for per user properties. @return: A C{list} of property names as two-tuples of namespace URI and local name. """ prefix = self.deadPropertyXattrPrefix try: attrs = iter(self.attrs) except IOError, e: if e.errno == errno.ENOENT: return [] raise HTTPError( StatusResponse(statusForFailure(Failure()), "Unable to list properties: %s", (self.resource.fp.path, )))
def do(action, property, removing=False): """ Perform action(property, request) while maintaining an undo queue. """ has = waitForDeferred(self.hasProperty(property, request)) yield has has = has.getResult() if has: oldProperty = waitForDeferred( self.readProperty(property, request)) yield oldProperty oldProperty = oldProperty.getResult() def undo(): return self.writeProperty(oldProperty, request) else: def undo(): return self.removeProperty(property, request) try: x = waitForDeferred(action(property, request)) yield x x.getResult() except KeyError, e: # Removing a non-existent property is OK according to WebDAV if removing: responses.add(responsecode.OK, property) yield True return else: # Convert KeyError exception into HTTPError responses.add( Failure(exc_value=HTTPError( StatusResponse(responsecode.FORBIDDEN, str( e)))), property) yield False return
def renderHTTP(self, request): """ Do the reverse proxy request and return the response. @param request: the incoming request that needs to be proxied. @type request: L{Request} @return: Deferred L{Response} """ self.log.info("{method} {uri} {proto}", method=request.method, uri=request.uri, proto="HTTP/%s.%s" % request.clientproto) # Check for multi-hop if not self.allowMultiHop: x_server = request.headers.getHeader("x-forwarded-server") if x_server: for item in x_server: if item.lower() == config.ServerHostName.lower(): raise HTTPError( StatusResponse(responsecode.BAD_GATEWAY, "Too many x-forwarded-server hops")) clientPool = getHTTPClientPool(self.poolID) proxyRequest = ClientRequest(request.method, request.uri, request.headers, request.stream) # Need x-forwarded-(for|host|server) headers. First strip any existing ones out, then add ours proxyRequest.headers.removeHeader("x-forwarded-host") proxyRequest.headers.removeHeader("x-forwarded-for") proxyRequest.headers.removeHeader("x-forwarded-server") proxyRequest.headers.addRawHeader("x-forwarded-host", request.host) proxyRequest.headers.addRawHeader("x-forwarded-for", request.remoteAddr.host) proxyRequest.headers.addRawHeader("x-forwarded-server", config.ServerHostName) return clientPool.submitRequest(proxyRequest)
def http_PROPPATCH(self, request): """ Respond to a PROPPATCH request. (RFC 2518, section 8.2) """ if not self.exists(): log.error("File not found: %s" % (self,)) raise HTTPError(responsecode.NOT_FOUND) x = waitForDeferred(self.authorize(request, (davxml.WriteProperties(),))) yield x x.getResult() # # Read request body # try: doc = waitForDeferred(davXMLFromStream(request.stream)) yield doc doc = doc.getResult() except ValueError, e: log.error("Error while handling PROPPATCH body: %s" % (e,)) raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, str(e)))