def get_qnet_progress(self, request, suffix=''): """The user progress checking handler""" abs_path = self.qnet_domain + self.qnet_progress # check absolute path and used element if abs_path != '' and self.qnet_element != '': # try to request try: url = self._format_api_url(abs_path) response = self._request_get(url) except Exception as e: return HTTPServerError(body="GET Qnet progress error: %s" % str(e)) # parse progress progress = self._convert_progress(response['progress']) self.is_done = progress['is_done'] self.score = progress['score'] # grade if self.is_done: self.runtime.publish(self, 'grade', { 'value': self.score, 'max_value': self.weight }) # return result return HTTPOk(headers={'Content-Type': 'application/json'}, body=json.dumps({ 'is_done': self.is_done, 'score': self.score, 'max_score': self.weight })) else: return HTTPServerError(body="Bad request to the Qnet platform")
def add_cluster(self, req, cluster_meta): """ Adds a new cluster to Daisy. :param req: The WSGI/Webob Request object :param image_meta: Mapping of metadata about cluster :raises HTTPBadRequest if x-cluster-name is missing """ self._enforce(req, 'add_cluster') cluster_name = cluster_meta["name"] if not cluster_name: raise ValueError('cluster name is null!') # target_systems = cluster_meta['target_systems'] # if not target_systems: # raise ValueError('target_systems is null!') if not cluster_meta.get('target_systems', None): cluster_meta['target_systems'] = "os" cluster_name_split = cluster_name.split('_') for cluster_name_info in cluster_name_split: if not cluster_name_info.isalnum(): raise ValueError( 'cluster name must be numbers or letters or underscores !') try: params = {"filters": dict(name=cluster_name)} cluster_name_repeat = \ registry.get_clusters_detail(req.context, **params) except Exception: pass else: if cluster_name_repeat: msg = _('cluster name [%s] is in use!') % cluster_name raise HTTPBadRequest(explanation=msg) if cluster_meta.get('nodes', None): orig_keys = list(cluster_meta['nodes']) for host_id in orig_keys: self._raise_404_if_host_deleted(req, host_id) node = registry.get_host_metadata(req.context, host_id) if node['status'] == 'in-cluster': msg = _("Forbidden to add host %s with status " "'in-cluster' in another cluster") % host_id raise HTTPForbidden(explanation=msg) if node.get('interfaces', None): interfaces = node['interfaces'] input_host_pxe_info = [ interface for interface in interfaces if interface.get('is_deployment', None) == 1 ] if not input_host_pxe_info and node.get('os_status', None) != 'active': msg = _( "The host %s has more than one dhcp server, " "please choose one interface for deployment") % \ host_id raise HTTPServerError(explanation=msg) print cluster_name print cluster_meta cluster_meta = registry.add_cluster_metadata(req.context, cluster_meta) return {'cluster_meta': cluster_meta}
def DELETE(self, req): """HTTP DELETE request handler.""" container_info = self.container_info(self.account_name, self.container_name) container_partition = container_info['partition'] containers = container_info['nodes'] req.acl = container_info['write_acl'] req.environ['swift_sync_key'] = container_info['sync_key'] object_versions = container_info['versions'] if object_versions: # this is a version manifest and needs to be handled differently lcontainer = object_versions.split('/')[0] prefix_len = '%03x' % len(self.object_name) lprefix = prefix_len + self.object_name + '/' last_item = None try: for last_item in self._listing_iter(lcontainer, lprefix, req.environ): pass except ListingIterNotFound: # no worries, last_item is None pass except ListingIterNotAuthorized, err: return err.aresp except ListingIterError: return HTTPServerError(request=req)
def __call__(self, env, start_response): try: return self.app(env, start_response) except Exception, err: self.logger.exception(_('Error: %s'), err) resp = HTTPServerError(request=Request(env), body='An error occurred', content_type='text/plain') return resp(env, start_response)
def get_qnet_status(self, request, suffix=''): """The lab status checking handler""" abs_path = self.qnet_domain + self.qnet_status # check absolute path and used element if abs_path != '' and self.qnet_element != '': # try to request try: url = self._format_api_url(abs_path) response = self._request_get(url) except Exception as e: return HTTPServerError(body="GET Qnet status error: %s" % str(e)) # return result return HTTPOk(headers={'Content-Type': 'application/json'}, body=json.dumps(response['wstatus'])) else: return HTTPServerError(body="Bad request to the Qnet platform")
def __call__(self, env, start_response): trans_id = env.get('HTTP_X_TRANS_ID') if not trans_id: trans_id = 'tx' + uuid.uuid4().hex env['HTTP_X_TRANS_ID'] = trans_id try: def my_start_response(status, response_headers, exc_info=None): trans_header = ('x-trans-id', trans_id) response_headers.append(trans_header) return start_response(status, response_headers, exc_info) return self.app(env, my_start_response) except Exception, err: self.logger.exception(_('Error: %s'), err) resp = HTTPServerError(request=Request(env), body='An error occurred', content_type='text/plain') resp.headers['x-trans-id'] = trans_id return resp(env, start_response)
def start_qnet_lab(self, request, suffix=''): """The starting handler""" abs_path = self.qnet_domain + self.qnet_path # check absolute path and used element if abs_path != '' and self.qnet_element != '': return { 'uri': abs_path.format(element=self.qnet_element) + ('?return_uri=%s' % request['from']) } else: return HTTPServerError(body="Bad request to the Qnet platform")
def __call__(self, env, start_response): """ If used, this should be the first middleware in pipeline. """ trans_id = 'tx' + uuid.uuid4().hex env['swift.trans_id'] = trans_id self.logger.txn_id = trans_id try: def my_start_response(status, response_headers, exc_info=None): trans_header = ('x-trans-id', trans_id) response_headers.append(trans_header) return start_response(status, response_headers, exc_info) return self.app(env, my_start_response) except (Exception, Timeout), err: self.logger.exception(_('Error: %s'), err) resp = HTTPServerError(request=Request(env), body='An error occurred', content_type='text/plain') resp.headers['x-trans-id'] = trans_id return resp(env, start_response)
def start_lab(self, request, suffix=''): self.started = True if self.course_name != '' and self.course_element != '' and self.iteration_id != '': html_academy_link = self.lab_url.format( name=self.course_name, element=self.course_element, ) return HTTPFound(location=html_academy_link) else: return HTTPServerError(explanation='Course Name, Course Element and Iteration ID fields are required!')
def GETorHEAD(self, req): """Handle HTTP GET or HEAD requests.""" container_info = self.container_info(self.account_name, self.container_name) req.acl = container_info['read_acl'] if 'swift.authorize' in req.environ: aresp = req.environ['swift.authorize'](req) if aresp: return aresp partition, nodes = self.app.object_ring.get_nodes( self.account_name, self.container_name, self.object_name) shuffle(nodes) resp = self.GETorHEAD_base(req, _('Object'), partition, self.iter_nodes(partition, nodes, self.app.object_ring), req.path_info, len(nodes)) # Whether we get a 416 Requested Range Not Satisfiable or not, # we should request a manifest because size of manifest file # can be not 0. After checking a manifest, redo the range request # on the whole object. if req.range: req_range = req.range req.range = None resp2 = self.GETorHEAD_base(req, _('Object'), partition, self.iter_nodes(partition, nodes, self.app.object_ring), req.path_info, len(nodes)) if 'x-object-manifest' not in resp2.headers: return resp resp = resp2 req.range = str(req_range) if 'x-object-manifest' in resp.headers: lcontainer, lprefix = \ resp.headers['x-object-manifest'].split('/', 1) lcontainer = unquote(lcontainer) lprefix = unquote(lprefix) try: listing = list(self._listing_iter(lcontainer, lprefix, req.environ)) except ListingIterNotFound: return HTTPNotFound(request=req) except ListingIterNotAuthorized, err: return err.aresp except ListingIterError: return HTTPServerError(request=req)
def __call__(self, env, start_response): if env['REQUEST_METHOD'] != 'PUT': return self.app(env, start_response) version, account, container, obj = split_path(env['PATH_INFO'], 1, 4, True) if not obj: return self.app(env, start_response) if not obj.lower().endswith('.jpg') and\ not obj.lower().endswith('.jpeg'): return self.app(env, start_response) extractor = MetaExtractor(env['wsgi.input']) env['wsgi.input'] = extractor try: resp = self._app_call(env) except Exception: resp = HTTPServerError(request=Request(env), body="error") return resp(env, start_response) start_response(self._response_status, self._response_headers, self._response_exc_info) status = int(self._response_status.split()[0]) if status < 200 or status > 300: return resp headers = {} for tag in extractor.exif_parser.tags: if tag.tag().startswith('Unknown'): continue if len(tag.value()) > MAX_META_VALUE_LENGTH: continue header = 'X-Object-Meta-' + tag.tag().replace(' ', '-') headers[header] = tag.value() # TODO: merge with the PUT headers self.logger.info(headers) post_req = make_pre_authed_request(env, method='POST', swift_source='JpegMeta', path=env['PATH_INFO'], headers=headers) post_resp = post_req.get_response(self.app) if not is_success(post_resp.status_int): self.logger.info('POST with JPEG headers failed: ' + str(post_resp.body)) return resp
def publish(self, environ): request = Request(environ) # xml-rpc only! if request.content_type.find('text/xml') >= 0: # FIXME pumazi: aww... this sucks! using the repoze.bfg.xmlrpc # (xmlrpc module) code was a mistake :( # The result of this is unloading the request twice =/ params, call_name = xmlrpclib.loads(request.body) storage = self.storage_factory(environ, self.config) # route the call call = xmlrpc_router(call_name) if call is not None: try: response = call(storage, request) except Exception, e: response = HTTPServerError(str(e)) else: response = HTTPNotFound()
def check(self, request, match): """Checks if the current request/match can be viewed. For WhoAuthentication this just delegates to the authenticate() API method, and uses the challenge() method if the user is not authorized for the request. """ # Don't auth if it's not required by the match. if match.get('auth') != 'True': return # If something further up the stack has already dealt with auth, # then things are highly unlikely to work properly. if 'REMOTE_USER' in request.environ: msg = 'The webserver appears to have handled authentication '\ 'internally, which is not compatible with this product.' raise HTTPServerError(msg) # Authenticate the user. api = self._api_factory(request.environ) identity = api.authenticate() if identity is None: self._raise_challenge(request) # Check against the username matched from the url, if any. username = identity.get("username") if match.get("username") not in (None, username): cef_kwds = {"signature": AUTH_FAILURE} if username is not None: cef_kwds["username"] = username err = "Username Does Not Match URL" self.logger.cef(err, 7, request.environ, self.config, **cef_kwds) self._raise_challenge(request) # Adjust environ to record the successful auth. # The identity must somehow get "userid" and "username" keys, # either from the authenticator or from an mdprovider. request.environ.pop("HTTP_AUTHORIZATION", None) match["user_id"] = identity["userid"] request.remote_user = identity["username"] request.environ["REMOTE_USER"] = identity["username"] request.user = User(identity["username"], identity["userid"]) request.user.update(identity)
def __call__(self, env, start_response): """ """ req = Request(env) self.loc.reload() if self.loc.age == 0: self.logger.warn( 'dispatcher relay rule is invalid, using old rules now.') if not self.is_keystone_proxy_path(req): return self.app(env, start_response) try: (loc_prefix, api_type) = self.location_api_check(req) except Exception: return HTTPPreconditionFailed(body='invalid PATH')(env, start_response) ks_port = self.keystone_auth_port \ if api_type == self.keystone_proxy_auth_path \ else self.keystone_admin_port servers = self.loc.swift_of(loc_prefix) if not servers: return HTTPPreconditionFailed(body='invalid Location prefix')( env, start_response) (succ_resps, fail_resps) = self.request_to_ks(req, servers, ks_port) if len(succ_resps) == 0: resp = fail_resps[0] if isinstance(resp, HTTPException): return resp(env, start_response) start_response('%s %s' % (resp.status, resp.reason), resp.getheaders()) return resp.read() if self.loc.is_merged(loc_prefix): try: (body, header) = self.ks_merge_response(succ_resps, loc_prefix) except Exception, err: return HTTPServerError(body=err)(env, start_response) res = Response(status='200 OK') res.headerlist = header res.body = body return res(env, start_response)
def __call__(self, env, start_response): req = Request(env) if env['REQUEST_METHOD'] not in ['GET']: return self.app(env, start_response) version, account, container, obj = split_path( env['PATH_INFO'], 1, 4, True) try: resp = self._app_call(env) except Exception: resp = HTTPServerError(request=req, body="error") return resp(env, start_response) status = int(self._response_status.split()[0]) if status < 200 or status > 300: start_response(self._response_status, self._response_headers, self._response_exc_info) return resp SLOmd5 = '' if req.params.get('multipart-manifest') == 'get': if req.params.get('format') == 'raw': resp = self.convert_segment_listing( self._response_headers, resp) else: h = hashlib.md5() segments = self._get_manifest_read(resp) for seg_dict in segments: if 'data' in seg_dict: continue sub_path = get_valid_utf8_str(seg_dict['name']) sub_cont, sub_obj = split_path(sub_path, 2, 2, True) h.update(self._fetch_sub_slo_segments(req, version, account, sub_cont, sub_obj)) SLOmd5 = h.hexdigest() self._post_slomd5_header(env, SLOmd5) return self.app(env, start_response)
def authenticate_user(self, request, config, username=None): """Authenticates a user and returns his id. "request" is the request received. The function makes sure that the user name found in the headers is compatible with the username if provided. It returns the user id from the database, if the password is the right one. """ environ = request.environ # If something further up the stack has already dealt with auth, # then things are highly unlikely to work properly. if 'REMOTE_USER' in environ: msg = 'The webserver appears to have handled authentication '\ 'internally, which is not compatible with this product.' raise HTTPServerError(msg) auth = environ.get('HTTP_AUTHORIZATION') if auth is not None: # for now, only supporting basic authentication # let's decipher the base64 encoded value if not auth.startswith('Basic '): self._log_cef('Authorization header contains unknown protocol', 7, environ) raise HTTPUnauthorized('Invalid token') auth = auth[len('Basic '):].strip() try: # Split in such a way as to preserve # passwords that contain ':'. user_name, password = base64.decodestring(auth).split(':', 1) except (binascii.Error, ValueError): self._log_cef('Authorization header is badly encoded', 7, environ) raise HTTPUnauthorized('Invalid token') # let's reject the call if the url is not owned by the user if (username is not None and user_name != username): self._log_cef('Username Does Not Match URL', 7, environ, config, user_name, AUTH_FAILURE) raise HTTPUnauthorized() # if this is an email, hash it. Save the original for logging and # debugging. remote_user_original = user_name try: user_name = extract_username(user_name) except UnicodeError: self._log_cef('Username contains invalid characters', 7, environ) raise HTTPBadRequest( 'Invalid characters specified in ' + 'username', {}, 'Username must be BIDI ' + 'compliant UTF-8') # let's try an authentication # the authenticate_user API takes a unicode UTF-8 for the password try: password = password.decode('utf8') except UnicodeDecodeError: self._log_cef('Password is not utf-8 encoded', 7, environ) raise HTTPUnauthorized() #first we need to figure out if this is old-style or new-style auth if hasattr(self.backend, 'generate_reset_code'): # XXX to be removed once we get the proper fix see bug #662859 if (hasattr(self.backend, 'check_node') and self.backend.check_node): user_id = self.backend.authenticate_user( user_name, password, environ.get('HTTP_HOST')) else: user_id = self.backend.authenticate_user( user_name, password) request.user = User(user_name, user_id) else: user = User(user_name) credentials = {"username": user_name, "password": password} attrs = [] check_node = self.config.get('auth.check_node') if check_node: attrs.append('syncNode') user_id = self.backend.authenticate_user( user, credentials, attrs) if not user_id: user_id = None user = None else: if (check_node and user.get('syncNode') != environ.get('HTTP_HOST')): self._log_cef('User authenticated to wrong node', 7, environ) user_id = None user = None request.user = user if user_id is None: err_user = user_name if remote_user_original is not None and \ user_name != remote_user_original: err_user += ' (%s)' % (remote_user_original) self._log_cef('User Authentication Failed', 5, environ, config, err_user, AUTH_FAILURE) raise HTTPUnauthorized() # we're all clear ! setting up REMOTE_USER request.remote_user = environ['REMOTE_USER'] = user_name # we also want to keep the password in clear text to reuse it # and remove it from the environ request.user_password = password request._authorization = environ['HTTP_AUTHORIZATION'] del environ['HTTP_AUTHORIZATION'] return user_id
"""Called by onLineFrom or onRawDataFrom to notify us that the Request has been fully read and we can begin processing it.""" try: response = yield self.requestHandler.findHandlerFor(request) except HTTPNotFound, e: response = e except: # We got an error while trying to to find a wsgi # application to handle the request, log it and try to # report something useful to the user. exc_info = sys.exc_info() self.log.exception('Unexpected Exception encountered while attempting to locate a handler for %s', request.path_info) #request.startResponse('500 Unexpeted',(('Content-type', 'text/plain'),),exc_info) response = HTTPServerError(detail="".join(traceback.format_exception(*exc_info)), request=request) response.text = response.html_body(request.environ) del exc_info # Valid responses are either WSGI Apps, Operation or of instances Responses if isinstance(response,self.Operation): try: response = yield response #yield (self.scheduler.call,) + response except Exception, e: exc_info = sys.exc_info() self.log.exception('Unexpected Exception encountered in coroutine %s', request.path_info) response = HTTPServerError(detail="<br/>\n".join(traceback.format_exception(*exc_info)), request=request) response.text = response.html_body(request.environ)
def __call__(self): """ :return httplib.HTTP(S)Connection in success, and webob.exc.HTTPException in failure """ if self.headers.has_key('content-length'): if int(self.headers['content-length']) >= MAX_FILE_SIZE: return HTTPRequestEntityTooLarge(request=self.req) parsed = urlparse(self.url) if self.proxy: proxy_parsed = urlparse(self.proxy) if self._proxy_request_check(parsed.path): host, port = self.split_netloc(proxy_parsed) path = self.url ssl = True if proxy_parsed.scheme == 'https' else False else: host, port = self.split_netloc(parsed) path = parsed.path ssl = True if parsed.scheme == 'https' else False self.headers['host'] = '%s:%s' % (host, port) if self.method == 'PUT' and len(parsed.path.split('/')) >= 5: if self.headers.has_key('content-length') and int( self.headers['content-length']) != 0: if not self.headers.has_key('expect'): self.headers['expect'] = '100-continue' chunked = self.req.headers.get('transfer-encoding') if isinstance(self.req.environ['wsgi.input'], str): reader = self.req.environ['wsgi.input'].read data_source = iter(lambda: reader(self.chunk_size), '') else: data_source = self.req.environ['wsgi.input'] bytes_transferred = 0 try: conn = self._connect_put_node(host, port, self.method, path, headers=self.headers, query_string=parsed.query, ssl=ssl) if not conn: return HTTPServiceUnavailable(request=self.req) with ContextPool(1) as pool: conn.failed = False conn.queue = Queue(10) pool.spawn(self._send_file, conn, path) while True: with ChunkReadTimeout(self.client_timeout): try: chunk = next(data_source) except StopIteration: if chunked: conn.queue.put('0\r\n\r\n') break except TypeError, err: self.logger.info('Chunk Read Error: %s' % err) break except Exception, err: self.logger.info('Chunk Read Error: %s' % err) return HTTPServerError(request=self.req) bytes_transferred += len(chunk) if bytes_transferred > MAX_FILE_SIZE: return HTTPRequestEntityTooLarge(request=self.req) if not conn.failed: conn.queue.put('%x\r\n%s\r\n' % (len(chunk), chunk) if chunked else chunk)
def handle_request(self, req): """ Entry point for proxy server. Should return a WSGI-style callable (such as webob.Response). :param req: webob.Request object """ try: self.logger.set_statsd_prefix('proxy-server') if req.content_length and req.content_length < 0: self.logger.increment('errors') return HTTPBadRequest(request=req, body='Invalid Content-Length') try: if not check_utf8(req.path_info): self.logger.increment('errors') return HTTPPreconditionFailed(request=req, body='Invalid UTF8') except UnicodeError: self.logger.increment('errors') return HTTPPreconditionFailed(request=req, body='Invalid UTF8') try: controller, path_parts = self.get_controller(req.path) p = req.path_info if isinstance(p, unicode): p = p.encode('utf-8') except ValueError: self.logger.increment('errors') return HTTPNotFound(request=req) if not controller: self.logger.increment('errors') return HTTPPreconditionFailed(request=req, body='Bad URL') if self.deny_host_headers and \ req.host.split(':')[0] in self.deny_host_headers: return HTTPForbidden(request=req, body='Invalid host header') self.logger.set_statsd_prefix('proxy-server.' + controller.server_type.lower()) controller = controller(self, **path_parts) if 'swift.trans_id' not in req.environ: # if this wasn't set by an earlier middleware, set it now trans_id = 'tx' + uuid.uuid4().hex req.environ['swift.trans_id'] = trans_id self.logger.txn_id = trans_id req.headers['x-trans-id'] = req.environ['swift.trans_id'] controller.trans_id = req.environ['swift.trans_id'] self.logger.client_ip = get_remote_client(req) try: handler = getattr(controller, req.method) getattr(handler, 'publicly_accessible') except AttributeError: return HTTPMethodNotAllowed(request=req) if path_parts['version']: req.path_info_pop() if 'swift.authorize' in req.environ: # We call authorize before the handler, always. If authorized, # we remove the swift.authorize hook so isn't ever called # again. If not authorized, we return the denial unless the # controller's method indicates it'd like to gather more # information and try again later. resp = req.environ['swift.authorize'](req) if not resp: # No resp means authorized, no delayed recheck required. del req.environ['swift.authorize'] else: # Response indicates denial, but we might delay the denial # and recheck later. If not delayed, return the error now. if not getattr(handler, 'delay_denial', None): return resp # Save off original request method (GET, POST, etc.) in case it # gets mutated during handling. This way logging can display the # method the client actually sent. req.environ['swift.orig_req_method'] = req.method return handler(req) except (Exception, Timeout): self.logger.exception(_('ERROR Unhandled exception in request')) return HTTPServerError(request=req)
def update_cluster(self, req, id, cluster_meta): """ Updates an existing cluster with the registry. :param request: The WSGI/Webob Request object :param id: The opaque cluster identifier :retval Returns the updated cluster information as a mapping """ self._enforce(req, 'update_cluster') if 'nodes' in cluster_meta: orig_keys = list(cluster_meta['nodes']) for host_id in orig_keys: self._raise_404_if_host_deleted(req, host_id) node = registry.get_host_metadata(req.context, host_id) if node['status'] == 'in-cluster': host_cluster = registry.get_host_clusters( req.context, host_id) if host_cluster[0]['cluster_id'] != id: msg = _("Forbidden to add host %s with status " "'in-cluster' in another cluster") % host_id raise HTTPForbidden(explanation=msg) if node.get('interfaces', None): interfaces = node['interfaces'] input_host_pxe_info = [ interface for interface in interfaces if interface.get('is_deployment', None) == 1 ] if not input_host_pxe_info and node.get('os_status', None) != 'active': msg = _( "The host %s has more than one dhcp server, " "please choose one interface for deployment") % \ host_id raise HTTPServerError(explanation=msg) if 'networks' in cluster_meta: orig_keys = list(cluster_meta['networks']) for network_id in orig_keys: self._raise_404_if_network_deleted(req, network_id) orig_cluster_meta = self.get_cluster_meta_or_404(req, id) # Do not allow any updates on a deleted cluster. # Fix for LP Bug #1060930 if orig_cluster_meta['deleted']: msg = _("Forbidden to update deleted cluster.") raise HTTPForbidden(explanation=msg, request=req, content_type="text/plain") try: cluster_meta = registry.update_cluster_metadata( req.context, id, cluster_meta) except exception.Invalid as e: msg = (_("Failed to update cluster metadata. Got error: %s") % utils.exception_to_str(e)) LOG.warning(msg) raise HTTPBadRequest(explanation=msg, request=req, content_type="text/plain") except exception.NotFound as e: msg = (_("Failed to find cluster to update: %s") % utils.exception_to_str(e)) LOG.warning(msg) raise HTTPNotFound(explanation=msg, request=req, content_type="text/plain") except exception.Forbidden as e: msg = (_("Forbidden to update cluster: %s") % utils.exception_to_str(e)) LOG.warning(msg) raise HTTPForbidden(explanation=msg, request=req, content_type="text/plain") except (exception.Conflict, exception.Duplicate) as e: LOG.warning(utils.exception_to_str(e)) raise HTTPConflict(body=_('Cluster operation conflicts'), request=req, content_type='text/plain') else: self.notifier.info('cluster.update', cluster_meta) return {'cluster_meta': cluster_meta}
bodies.append(response.read()) if response.status >= HTTP_INTERNAL_SERVER_ERROR: self.error_occurred(conn.node, _('ERROR %(status)d %(body)s From Object Server ' \ 're: %(path)s') % {'status': response.status, 'body': bodies[-1][:1024], 'path': req.path}) elif is_success(response.status): etags.add(response.getheader('etag').strip('"')) except (Exception, Timeout): self.exception_occurred( conn.node, _('Object'), _('Trying to get final status of PUT to %s') % req.path) if len(etags) > 1: self.app.logger.error( _('Object servers returned %s mismatched etags'), len(etags)) return HTTPServerError(request=req) etag = len(etags) and etags.pop() or None while len(statuses) < len(nodes): statuses.append(HTTP_SERVICE_UNAVAILABLE) reasons.append('') bodies.append('') resp = self.best_response(req, statuses, reasons, bodies, _('Object PUT'), etag=etag) if source_header: resp.headers['X-Copied-From'] = quote( source_header.split('/', 2)[2]) if 'last-modified' in source_resp.headers:
def __call__(self): """ :return httplib.HTTP(S)Connection in success, and webob.exc.HTTPException in failure """ if self.headers.has_key('content-length'): if int(self.headers['content-length']) >= MAX_FILE_SIZE: return HTTPRequestEntityTooLarge(request=self.req) parsed = urlparse(self.url) if self.proxy: proxy_parsed = urlparse(self.proxy) if self._proxy_request_check(parsed.path): host, port = self.split_netloc(proxy_parsed) path = self.url else: host, port = self.split_netloc(parsed) path = parsed.path self.headers['host'] = '%s:%s' % (host, port) if self.method == 'PUT' and len(parsed.path.split('/')) == 5: chunked = self.req.headers.get('transfer-encoding') reader = self.req.environ['wsgi.input'].read data_source = iter(lambda: reader(self.chunk_size), '') bytes_transferred = 0 # pile = GreenPile() # pile.spawn(self._connect_server, host, port, self.method, path, self.headers, parsed.query) # conns = [conn for conn in pile if conn] # conn = conns[0] try: with ConnectionTimeout(self.conn_timeout): conn = http_connect_raw(host, port, self.method, path, headers=self.headers, query_string=parsed.query) with ContextPool(1) as pool: conn.failed = False conn.queue = Queue(10) pool.spawn(self._send_file, conn, path) while True: with ChunkReadTimeout(self.client_timeout): try: chunk = next(data_source) except StopIteration: if chunked: conn.queue.put('0\r\n\r\n') break except TypeError, err: self.logger.info('Chunk Read Error: %s' % err) break except Exception, err: self.logger.info('Chunk Read Error: %s' % err) return HTTPServerError(request=self.req) bytes_transferred += len(chunk) if bytes_transferred > MAX_FILE_SIZE: return HTTPRequestEntityTooLarge(request=self.req) if not conn.failed: conn.queue.put('%x\r\n%s\r\n' % (len(chunk), chunk) if chunked else chunk)
self.signature_methods[signature_cls.name] = signature_cls() # FIXME: the nonce list heavily depends on traffic usage nonce_cache_size = self._config.get('nonce_cache_size', 20000) self.nonce_list = NOnceList(nonce_cache_size) def __call__(self, environ, start_response): # 1. get the webob request and oauth request req = OAuthRequest(environ) try: response = self.process(self.get_storage(environ), req) except Error, e: response = HTTPBadRequest(e.message) except: response = HTTPServerError( "An unknown problem has occured, " "please contact your site administrator for help with this " "issue.") return response(environ, start_response) def get_storage(self, environ): """Transparent access to the storage without worrying about the factory.""" return self.storage_factory(environ, self._config) def process(self, storage, request): """Process the OAuth request.""" # 2. determine if the request is an oauth request consumer_key = request.oauth_params.get('oauth_consumer_key', None) oauth_token_key = request.oauth_params.get('oauth_token', None) if len(request.oauth_params) == 0: # not an oauth reqeust raise NotAnOAuthRequest("The request made does not contain one "