def __call__(self, env, start_response): Config = ConfigParser() Config.read(configfile) params = {"host": "", "user": "", "database": "", "port": ""} for param in params: if not Config.has_option("BlobStore", param): print "Malformed configuration file: mission option %s in section %s" % (param, "BlobStore") sys.exit(1) params[param] = Config.get("BlobStore", param) req = Request(env) resp = Response(status=200, content_type="text/plain") #engine = create_engine("mysql+mysqldb://%s:%s@%s:%s/%s?charset=utf8&use_unicode=0" % # (params["user"], secret.BlobSecret, params["host"], params["port"], params["database"]), pool_recycle=3600) Base = declarative_base(bind=engine) local.Session = [] local.FileEntry = [] Session.append(sessionmaker(bind=engine)) FileEntry.append(makeFileEntry(Base)) if req.path.startswith('/fx'): if req.method == "GET": resp.status_code, filename, resp.content_type, resp.response = self.__download(req) if resp.content_type == "application/octet-stream": resp.headers["Content-Disposition"] = "attachment; filename=%s" % filename return resp(env, start_response) elif req.method == "POST": resp.content_type="text/plain" resp.response = self.__upload(req) return resp(env, start_response) else: resp.status_code = 404 resp.content_type="text/plain" resp.response = "" return resp(env, start_response)
def add_response(self, data, status=None, headers=None): response = Response(data) response.status_code = status or httplib.OK response.headers = headers or { 'Content-Type': 'text/html; charset=UTF-8' } self.responses.append(response)
def digest_challenge_response(request, qop, algorithm, stale=False): response = Response() response.status_code = 401 # RFC2616 Section4.2: HTTP headers are ASCII. That means # request.remote_addr was originally ASCII, so I should be able to # encode it back to ascii. Also, RFC2617 says about nonces: "The # contents of the nonce are implementation dependent" nonce = H( b''.join([ getattr(request, 'remote_addr', u'').encode('ascii'), b':', str(time.time()).encode('ascii'), b':', os.urandom(10) ]), algorithm) opaque = H(os.urandom(10), algorithm) auth = WWWAuthenticate("digest") auth.set_digest('*****@*****.**', nonce, opaque=opaque, qop=('auth', 'auth-int') if qop is None else (qop, ), algorithm=algorithm) auth.stale = stale response.headers['WWW-Authenticate'] = auth.to_header() return response
def humanify(obj, status_code=200): """ Gets an obj and possibly a status code and returns a flask Resonse with a jsonified obj, with newlines. >>> humanify({"a": 1}) <Response 13 bytes [200 OK]> >>> humanify({"a": 1}, 404) <Response 13 bytes [404 NOT FOUND]> >>> humanify({"a": 1}).get_data() '{\\n "a": 1\\n}\\n' >>> humanify([1,2,3]).get_data() '[\\n 1, \\n 2, \\n 3\\n]\\n' """ # jsonify function doesn't work with lists if type(obj) == list: data = json.dumps(obj, default=json_util.default, indent=2) + '\n' elif type(obj) == pymongo.cursor.Cursor: rv = [] for doc in obj: doc['_id'] = str(doc['_id']) rv.append(dumps(doc, indent=2)) data = '[' + ',\n'.join(rv) + ']' + '\n' else: data = dumps(obj, default=json_util.default, indent=2, cls=MongoJsonEncoder) data += '\n' resp = Response(data, mimetype='application/json') resp.status_code = status_code return resp
def drip(request): """Drips data over a duration after an optional initial delay.""" args = CaseInsensitiveDict(request.args.items()) duration = float(args.get('duration', 2)) numbytes = min(int(args.get('numbytes', 10)), (10 * 1024 * 1024)) # set 10MB limit code = int(args.get('code', 200)) if numbytes <= 0: response = Response('number of bytes must be positive', status=400) return response delay = float(args.get('delay', 0)) if delay > 0: time.sleep(delay) pause = duration / numbytes def generate_bytes(): for i in xrange(numbytes): yield u"*".encode('utf-8') time.sleep(pause) response = Response(generate_bytes(), headers={ "Content-Type": "application/octet-stream", "Content-Length": str(numbytes) }) response.status_code = code return response
def humanify(obj, status_code=200): """ Gets an obj and possibly a status code and returns a flask Resonse with a jsonified obj, not suitable for humans >>> humanify({"a": 1}) <Response 8 bytes [200 OK]> >>> humanify({"a": 1}, 404) <Response 8 bytes [404 NOT FOUND]> >>> humanify({"a": 1}).get_data() '{"a": 1}' >>> humanify([1,2,3]).get_data() '[1, 2, 3]' """ # TODO: refactor the name to `response` # jsonify function doesn't work with lists if type(obj) == list: data = json.dumps(obj, default=json_util.default) elif type(obj) == pymongo.cursor.Cursor: rv = [] for doc in obj: doc['_id'] = str(doc['_id']) rv.append(dumps(doc)) data = '[' + ',\n'.join(rv) + ']' + '\n' else: data = dumps(obj, default=json_util.default, cls=MongoJsonEncoder) resp = Response(data, mimetype='application/json') resp.status_code = status_code return resp
def __call__(self, env, start_response): req = Request(env) Config = ConfigParser() Config.read(configfile) params = {"host": "", "user": "", "database": "", "port": ""} for param in params: if not Config.has_option("MySQL", param): print "Malformed configuration file: mission option %s in section MySQL" % (param) sys.exit(1) params[param] = Config.get("MySQL", param) #engine = create_engine("mysql+mysqldb://%s:%s@%s:%s/%s?charset=utf8&use_unicode=0" % # (params["user"], secret.MySQL, params["host"], params["port"], params["database"]), pool_recycle=3600) Base = declarative_base(bind=engine) local.Session = [] local.User = [] local.MethodEmail = [] local.Session.append(sessionmaker(bind=engine)) local.User.append(makeUser(Base)) local.MethodEmail.append(makeMethodEmail(Base)) resp = Response(status=200) if req.path == '/register': resp.content_type = "text/html" resp.response = self.__register(req) return resp(env, start_response) elif req.path == '/regemail1': resp.content_type = "text/html" resp.response = self.__addEmailAuth1(req) return resp(env, start_response) elif req.path == '/regemail2': resp.content_type = "text/html" resp.response = self.__addEmailAuth2(req) return resp(env, start_response) elif req.path == '/regemail3': resp.content_type = "text/html" resp.response = self.__addEmailAuth3(req) return resp(env, start_response) elif req.path == '/regemailkill': resp.content_type = "text/html" resp.response = self.__removeEmailAuth(req) return resp(env, start_response) elif req.path == '/regemaillist': resp.content_type = "text/plain" resp.response = self.__listEmailAuth(req) return resp(env, start_response) elif req.path == '/auth' and req.values.has_key("email") and req.values.has_key("password"): resp.content_type = "text/plain" resp.response = [self.__authenticateByEmail(req)] return resp(env, start_response) elif req.path == '/auth' and req.values.has_key("uid"): resp.content_type = "text/plain" uid = self.__uid(req) if uid == None: uid = "" resp.response = [uid] return resp(env, start_response) else: resp.status_code = 404 resp.response = [""] return resp(env, start_response)
def _application(self, environ, start_response): request = Request(environ) self.logger.info(request.full_path) status_code = 200 headers = {'Content-Type': 'application/json'} content = '' if request.path == '/': # 接管主页,因为所有请求需要token,主页转发不能正常工作 headers = {'Content-Type': 'text/html'} content = '<h1><a href="https://github.com/xiyaoWong/iotbot-http-transfer">iotbot http tranfer</a><h1>' elif request.path.strip('/') == 'favicon.ico': status_code = 301 del headers['Content-Type'] headers['location'] = 'https://cdn.jsdelivr.net/gh/xiyaowong/FileHost/transfer.png' elif request.path.strip('/') == 'genToken': # 处理token生成请求 key = request.args.get('key') if key == self.key: token = self._genarate_token('ok, it\' funny.') content = json.dumps({'token': token}) else: content = '{"Ret":1111, "Msg":"key错误"}' else: # 处理其他请求 # 鉴权 token = request.args.get('token') or request.headers.get('Authorization') if not self._check_token(token): # 大胆,狗贼 content = '{"Ret":2222, "Msg":"无效的token"}' else: try: resp = requests.request( request.method, '{}{}?{}'.format( 'http://{}:{}'.format(self.iotbot_host, self.iotbot_port), request.path, request.query_string.decode()), headers=request.headers, data=request.data, timeout=self.timeout ) except requests.Timeout as e: self.logger.warning(e) content = '{"Ret":3333, "Msg":"请求响应超时"}' except requests.ConnectionError as e: self.logger.exception(e) content = '{"Ret":4444, "Msg":"连接错误"}' except Exception as e: self.logger.exception(e) content = '{"Ret":5555, "Msg":"请求响应失败"}' else: content = resp.content status_code = resp.status_code headers = resp.headers response = Response(content) response.status = HTTP_STATUS_CODES[status_code] response.status_code = status_code for header_name, header_value in headers.items(): response.headers[header_name] = header_value return response(environ, start_response)
def redirect_to(request): """302/3XX Redirects to the given URL.""" args = CaseInsensitiveDict(request.args.items()) # We need to build the response manually and convert to UTF-8 to prevent # werkzeug from "fixing" the URL. This endpoint should set the Location # header to the exact string supplied. response = Response() response.status_code = 302 if 'status_code' in args: status_code = int(args['status_code']) if status_code >= 300 and status_code < 400: response.status_code = status_code response.headers['Location'] = args['url'].encode('utf-8') return response
def __call__(self, request): try: response = self.responses[len(self.requests)] except IndexError: response = Response("No prepared response") response.status_code = httplib.NOT_IMPLEMENTED return response self.requests.append(request) return response
def serve_content(file_handle: TextIO, content_type): file_handle.seek(0) content = file_handle.read() resp = Response() resp.content_type = content_type resp.status_code = 200 resp.data = content resp.freeze() return resp
def __call__(self, env, start_response): req = Request(env) Config = ConfigParser() Config.read(configfile) params = {"host": "", "user": "", "database": "", "port": ""} for param in params: if not Config.has_option("MySQL", param): print "Malformed configuration file: mission option %s in section MySQL" % (param) sys.exit(1) params[param] = Config.get("MySQL", param) #print params #engine = create_engine("mysql+mysqldb://%s:%s@%s:%s/%s?charset=utf8&use_unicode=0" % # (params["user"], secret.MySQL, params["host"], params["port"], params["database"]), pool_recycle=3600) Base = declarative_base(bind=engine) local.Session = [] local.Package = [] local.Session.append(sessionmaker(bind=engine)) local.Package.append(makePackage(Base)) resp = Response(status=200, content_type="text/plain") if req.path == '/pkg/upload': resp.content_type="text/html" resp.response = self.__upload(req) return resp(env, start_response) elif req.path == '/pkg/sdk': resp.content_disposition="application/force-download" resp.content_type="application/python" resp.headers.add("Content-Disposition", "attachment; filename=appcfg.py") f = open("appcfg.py").read().replace("__REPO_UPLOAD__", '"%s"' % (req.host_url + 'pkg/upload')) resp.headers.add("Content-Length", str(len(f))) resp.response = [f] return resp(env, start_response) elif req.path.startswith('/pkg'): resp.status_code, resp.content_encoding, resp.response = self.__download(req) return resp(env, start_response) else: resp.status_code = 404 resp.response = [""] return resp(env, start_response)
def relative_redirect_n_times(request, n): """302 Redirects n times.""" assert n > 0 response = Response() response.status_code = 302 if n == 1: return redirect( request.url_for('view_method', values={'method': 'get'})) return response response.headers['Location'] = request.url_for('relative_redirect_n_times', values=dict(n=n - 1)) return response
def application(request): try: # Parse the JSON in the request try: data = loads(request.stream.read()) except ValueError: raise BadRequest() # Grab the function to execute try: method = getattr(backend, data['method']) except (KeyError, IndexError): raise BadRequest() if method is None: raise NotFound() # Get the args and kwargs args = data.get('args', []) kwargs = data.get('kwargs', {}) kwargs = dict( ((k.encode('utf-8'), v) for k, v in kwargs.iteritems())) # Attempt to call the method with the params, or catch the # exception and pass that back to the client try: response = Response( dumps({ 'id': data.get('id'), 'result': method(*args, **kwargs), 'error': None, })) except (KeyboardInterrupt, SystemExit): raise except Exception, e: print e response = Response( dumps({ 'id': data.get('id'), 'result': None, 'error': ''.join(traceback.format_exception(*sys.exc_info())), })) # Finish up and return the response response.headers['Content-Type'] = 'application/json' response.headers['Content-Length'] = len(response.data) response.status_code = 200 return response
def application(request): try: # Parse the JSON in the request try: data = loads(request.stream.read()) except ValueError: raise BadRequest() # Grab the function to execute try: method = getattr(backend, data['method']) except (KeyError, IndexError): raise BadRequest() if method is None: raise NotFound() # Get the args and kwargs args = data.get('args', []) kwargs = data.get('kwargs', {}) kwargs = dict(((k.encode('utf-8'), v) for k, v in kwargs.iteritems())) # Attempt to call the method with the params, or catch the # exception and pass that back to the client try: response = Response(dumps({ 'id': data.get('id'), 'result': method(*args, **kwargs), 'error': None, })) except (KeyboardInterrupt, SystemExit): raise except Exception, e: print e response = Response(dumps({ 'id': data.get('id'), 'result': None, 'error': ''.join(traceback.format_exception(*sys.exc_info())), })) # Finish up and return the response response.headers['Content-Type'] = 'application/json' response.headers['Content-Length'] = len(response.data) response.status_code = 200 return response
def __call__(self, environ, start_response): path_info = environ['PATH_INFO'] path = re.sub(self.prefix, '', path_info) prefix = path_info[:-len(path)] if prefix.endswith("/ui"): prefix = prefix[:-3] if path == "/": path = "/index.html" if path == "/index.html": with open(swagger_ui_3_path + path) as fh: content = fh.read() content = content.replace( "https://petstore.swagger.io/v2/swagger.json", prefix + "/openapi.yaml") resp = Response() resp.content_type = 'text/html' resp.status_code = 200 resp.data = content resp.freeze() return resp(environ, start_response) return serve_file(swagger_ui_3_path + path)(environ, start_response)
def range_request(request, numbytes): """Streams n random bytes generated with given seed, at given chunk size per packet.""" if numbytes <= 0 or numbytes > (100 * 1024): response = Response(headers={ 'ETag': 'range%d' % numbytes, 'Accept-Ranges': 'bytes' }) response.status_code = 404 response.data = 'number of bytes must be in the range (0, 10240]' return response params = CaseInsensitiveDict(request.args.items()) if 'chunk_size' in params: chunk_size = max(1, int(params['chunk_size'])) else: chunk_size = 10 * 1024 duration = float(params.get('duration', 0)) pause_per_byte = duration / numbytes request_headers = get_headers(request) first_byte_pos, last_byte_pos = get_request_range(request_headers, numbytes) range_length = (last_byte_pos + 1) - first_byte_pos if first_byte_pos > last_byte_pos or first_byte_pos not in xrange( 0, numbytes) or last_byte_pos not in xrange(0, numbytes): response = Response( headers={ 'ETag': 'range%d' % numbytes, 'Accept-Ranges': 'bytes', 'Content-Range': 'bytes */%d' % numbytes, 'Content-Length': '0', }) response.status_code = 416 return response def generate_bytes(): chunks = bytearray() for i in xrange(first_byte_pos, last_byte_pos + 1): # We don't want the resource to change across requests, so we need # to use a predictable data generation function chunks.append(ord('a') + (i % 26)) if len(chunks) == chunk_size: yield (bytes(chunks)) time.sleep(pause_per_byte * chunk_size) chunks = bytearray() if chunks: time.sleep(pause_per_byte * len(chunks)) yield (bytes(chunks)) content_range = 'bytes %d-%d/%d' % (first_byte_pos, last_byte_pos, numbytes) response_headers = { 'Content-Type': 'application/octet-stream', 'ETag': 'range%d' % numbytes, 'Accept-Ranges': 'bytes', 'Content-Length': str(range_length), 'Content-Range': content_range } response = Response(generate_bytes(), headers=response_headers) if (first_byte_pos == 0) and (last_byte_pos == (numbytes - 1)): response.status_code = 200 else: response.status_code = 206 return response
def __call__(self, env, start_response): local.application = self req = Request(env) resp = Response(status=200) start_response('200 OK', [('Content-Type', 'text/plain')]) if req.path == '/start': # Have all arguments been passed? if not (req.values.has_key("protocol") and req.values.has_key("ncli") and req.values.has_key("nsrv") and req.values.has_key("rep")): resp.status_code = 500 resp.response = ["One of the mandatory arguments has been omitted [protocol, ncli, nsrv, rep]"] return resp(env, start_response) # Does protocol have a valid value? protocol = req.values["protocol"] if protocol not in protocols: resp.status_code = 500 resp.response = ["Protocol specified is not implemented; must be one of [ftp, http, udt, gridftp, torrent]"] return resp(env, start_response) # Do these arguments have valid numeric values? try: ncli, nsrv, rep = int(req.values["ncli"]), int(req.values["nsrv"]), int(req.values["rep"]) except: resp.status_code = 500 resp.response = ["Unable to parse a mandatory numeric argument"] return resp(env, start_response) # Do the numeric arguments make sense? if ncli < 1 or nsrv < 1 or rep < 1: resp.status_code = 500 resp.response = ["Go screw yourself"] return resp(env, start_response) if ncli > len(clients): resp.status_code = 500 resp.response = ["We don't have that many clients available. Current maximum is %d" % len(clients)] return resp(env, start_response) if nsrv > len(servers): resp.status_code = 500 resp.response = ["We don't have that many servers available. Current maximum is %d" % len(servers)] return resp(env, start_response) # Has the previous experiment been finished already? For that, its nclients*replication must be equal to the number of associated measurements res = my.query("select max(id) from experiment") last_exp_id = res.rows[0][0] if last_exp_id: res = my.query("select replication, ncli from experiment where id=%s", (last_exp_id,)) rep_prev, ncli_prev = res.rows[0][0], res.rows[0][1] res = my.query("select count(*) from measurement where experiment_id=%s", (last_exp_id,)) cnt = res.rows[0][0] if cnt < rep_prev*ncli_prev: resp.status_code = 500 resp.response = ["Unable to comply, experiment in progress"] return resp(env, start_response) f = NamedTemporaryFile(delete=False) f.write(generatehaproxycfg(nsrv)) f.close() local.ssh = paramiko.SSHClient() local.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) local.ssh.connect(proxy, username='******', key_filename='/home/rumith/.ssh/awskeys.pem') local.scp = scp.SCPClient(local.ssh.get_transport()) local.scp.put(f.name, "/etc/haproxy/haproxy.cfg") if protocol == "http": stdin, stdout, stderr = local.ssh.exec_command('pkill haproxy; haproxy -f /etc/haproxy/haproxy.cfg') local.ssh.close() os.unlink(f.name) expcount, experiment_id = my.query("insert into experiment (started, protocol, ncli, nsrv, replication) values ((select now()), %s, %s, %s, %s)", (protocol, ncli, nsrv, rep)) # Copy the required protocol download programs to the clients used and start them for i in range(ncli): local.ssh = paramiko.SSHClient() local.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) local.ssh.connect(clients[i], username='******', key_filename='/home/rumith/.ssh/id_rsa') local.scp = scp.SCPClient(local.ssh.get_transport()) local.scp.put("protocol-%s.sh" % protocol, "/home/protobench") if protocol == "http": stdin, stdout, stderr = local.ssh.exec_command('cd /home/protobench && ./protocol-%s.sh %s %s 1 > /dev/null 2>&1 &' % (protocol, proxy, experiment_id)) local.ssh.close() resp.response = ["Experiment %d x %d [%s] successfully started; replication %d" % (nsrv, ncli, protocol, rep) ] return resp(env, start_response) elif req.path == '/done': # Did the client pass all the required arguments? if not (req.values.has_key("expid") and req.values.has_key("runid") and req.values.has_key("bw")): resp.status_code = 500 resp.response = ["One of the mandatory arguments has been omitted [expid, runid, bw]"] return resp(env, start_response) # Do they have legal values? try: expid, runid, bandwidth = int(req.values["expid"]), int(req.values["runid"]), int(req.values["bw"]) except: resp.status_code = 500 resp.response = ["Unable to parse mandatory arguments"] return resp(env, start_response) # Is there really such an experiment to commit to? res = my.query("select count(*) from experiment where id = %s", (req.values["expid"],)) expcnt = res.rows[0][0] if expcnt == 0: resp.status_code = 500 resp.response = ["No such experiment"] return resp(env, start_response) # Is this run being reported for the first time from this host? res = my.query("select count(*) from measurement where experiment_id = %s and run_id = %s and client_host = %s", (expid, runid, req.remote_addr)) runcheck = res.rows[0][0] if runcheck > 0: resp.status_code = 500 resp.response = ["Such a run already exists"] return resp(env, start_response) # Does bandwidth have a valid value? if bandwidth < 0: resp.status_code = 500 resp.response = ["Bad bandwidth value"] return resp(env, start_response) # Commit the measurement my.query("insert into measurement (experiment_id, run_id, bandwidth, client_host) values (%s, %s, %s, %s)", (expid, runid, bandwidth, req.remote_addr)) # Do we have enough replication for this host/experiment pair, or should we launch the task again? res = my.query("select replication, protocol from experiment where id=%s", (expid,)) replication, protocol = res.rows[0][0], res.rows[0][1] res = my.query("select count(*) from measurement where experiment_id=%s and client_host=%s", (expid, req.remote_addr)) runcnt = res.rows[0][0] if replication > runcnt: local.ssh = paramiko.SSHClient() local.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) local.ssh.connect(req.remote_addr, username='******', key_filename='/home/rumith/.ssh/id_rsa') if protocol == "http": stdin, stdout, stderr = local.ssh.exec_command('cd /home/protobench && ./protocol-%s.sh %s %s %s > /dev/null 2>&1 &' % (protocol, proxy, expid, (runid + 1))) local.ssh.close() else: # If we have enough replication for this one, maybe we have everything from other clients, too, and can finish the experiment? res = my.query("select replication, ncli from experiment where id=%s", (expid,)) rep, ncli = res.rows[0][0], res.rows[0][1] res = my.query("select count(*) from measurement where experiment_id=%s", (expid,)) cnt = res.rows[0][0] if cnt > 0 and cnt == rep*ncli: bw = [] res = my.query("select bandwidth from measurement where experiment_id=%s", (expid,)) for r in res.rows: bw.append(r[0]) bsum = float(sum(bw)) / rep sigma = 0 for i in range(rep): delta = bw[i] - bsum sigma += delta**2 bw, mse = bsum, sqrt(sigma/rep) my.query("update experiment set ended=(select now()), bandwidth=%s, mse=%s where id=%s", (bw, mse, expid)) return resp(env, start_response) elif req.path == '/status': return resp(env, start_response) else: resp.status_code = 404 resp.response = ["Invalid request"] return resp(env, start_response)