FLASK: Serving file to browser behind API proxy - python

When the user enters http://example2.com:5500/?param=x the code below generates a data.csv file and serves it to the browser. It works perfectly like this.
However, I have deployed it behind an API proxy, so that the user makes a call to http://example1.com/?param=x which is internally transformed into http://example2.com:5500/?param=x.
As a result, instead of serving data.csv to the browser as before, it displays on the browser all the data.csv content. The view source-code feature shows exactly what data.csv should contain, without any HTML headers, just the data.csv content, but it is not being served as attachement. Any ideas?
from flask import make_response
#app.route('/', methods = ['GET'])
def get_file():
alldata = []
while len(new_data) > 0:
new_data = api.timeline(max_id=oldest)
alldata.extend(new_data)
oldest = alldata[-1].id - 1
outdata = ""
for data in alldata:
outdata += ",".join(data) + "\n"
response = make_response(outdata)
response.headers["Content-Disposition"] = "attachment; filename=data.csv"
return response
if __name__ == '__main__':
app.run(host = app.config['HOST'], port = app.config['PORT'])
EDIT: Included mapping code to transform request to example1.com to example2.com (secret_url)
# This is example1.com
#app.route("/api/<projectTitle>/<path:urlSuffix>", methods=['GET'])
def projectTitlePage(projectTitle, urlSuffix):
projectId = databaseFunctions.getTitleProjectId(projectTitle)
projectInfo = databaseFunctions.getProjectInfo(projectId)
redirectionQueryString = re.sub('apikey=[^&]+&?', '', request.query_string).rstrip('&')
redirectionUrl = projectInfo['secretUrl'].rstrip('/')
if urlSuffix is not None:
redirectionUrl += '/' + urlSuffix.rstrip('/')
redirectionUrl += '/?' + redirectionQueryString
redirectionHeaders = request.headers
print request.args.to_dict(flat=False)
try:
r = requests.get(redirectionUrl, data=request.args.to_dict(flat=False), headers=redirectionHeaders)
except Exception, e:
return '/error=Error: bad secret url: ' + projectInfo.get('secretUrl')
return r.text

Your homegrown proxy is not returning headers back to the application. Try this:
#app.route("/api/<projectTitle>/<path:urlSuffix>", methods=['GET'])
def projectTitlePage(projectTitle, urlSuffix):
# ...
return r.text, r.status_code, r.headers

Related

Flask - cookies won't create

so i have two 'cookies' functions outside of routes to make code more organized
def get_cookie():
# ip_address = request.environ['REMOTE_ADDR']
ip_address = "X"
access_token = os.environ.get('ipinfo_key')
handler = ipinfo.getHandler(access_token=access_token)
details = handler.getDetails(ip_address=ip_address)
print(details.all)
resp = make_response(render_template('base.html'))
resp.set_cookie('ip',ip_address)
app.logger.info("Creating cookies...")
print(details.all['city'])
print(details.all['postal'])
print(details.all['latitude'])
print(details.all['longitude'])
resp.set_cookie('city',details.all['city'])
resp.set_cookie('postal',details.all['postal'])
resp.set_cookie('latitude',details.all['latitude'])
resp.set_cookie('longitude',details.all['longitude'])
app.logger.info("Cookies has been created.")
return resp
def check_cookie():
app.logger.info("Checking cookies...")
if 'city' in request.cookies:
app.logger.info("Cookies already exists.")
else:
app.logger.info("No cookie found.Creating new ones...")
return get_cookie()
check_cookie() function check whether user have cookie named city and if don't triggers get_cookie() function
There's my simple main route.
#app.route('/')
def base():
check_cookie()
return render_template('base.html')
If i try to log my location info from API everything is going right but cookies aren't created... Any tips? ;/

Flask redirect page after response is complete

So I currently have button in my html script that calls the route /return-files. This route returns a response with a zipped file and I also disabled any caching since I had issue with trying to get a new file each time this response is made. This is working well, but since i cannot return multiple things ( a response and a redirect) I cannot refresh my current page after sending the user a the zip file. Now I have read many solutions such as using javascript to create consecutive responses. I am looking for the simplest technique. Source code bellow thanks for all help.
#app.route('/return-files')
def creareturn_files_tut():
global itemsList
global clientName
try:
if len(itemsList) <= 0:
flash("The itemList was found to contain no items")
else:
taxPercent = 0.13
ziped = FileHandler(clientName, itemsList, taxPercent)
file = ziped.addToZip()
os.remove(ziped.excelFileName)
os.remove(ziped.wordFileName)
# os.remove(file)
itemsList = []
clientName = None
response = make_response(send_file(file, file, as_attachment=True))
# remove cache for the file so that a new file can be sent each time
response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
response.headers["Pragma"] = "no-cache"
response.headers["Expires"] = "0"
response.headers['Cache-Control'] = 'public, max-age=0'
return response
# return out
except Exception as e:
return str(e)
You can use send_from_directory() or send_file() like this:
file = ziped.addToZip()
os.remove(ziped.excelFileName)
os.remove(ziped.wordFileName)
itemsList = []
clientName = None
return send_from_directory(directory='', filename=file, as_attachment=True, cache_timeout=0)
or
file = ziped.addToZip()
os.remove(ziped.excelFileName)
os.remove(ziped.wordFileName)
itemsList = []
clientName = None
return send_file(file, cache_timeout=0, as_attachment=True)
Note that caching is disabled by setting cache_timeout to 0.

HP ALM results attachment and status update using python

Challenge : Attach screenshots to Tests in TestLab , update status as PASS/FAIL steps wise (currently updating pass status is enough)
I am expected to write a script in python , to attach test results to the testcases present in test lab, then for each test step Expected result to be set as "As Expected" and pass the TC step by step.
Ie while performing manually, we select the case , click run and then enter "As expected" in expected output area and pass that step, and perfrom this for all teststeps on the test case. This need to be automated. I hav a folder which has Screenshots(similar to TC name), so script shoudl upload the screenshots and update the status.
What I have tried so far :
I was able to connect to alm , with partial testcase name, I was able to pull full testcase name from testplan, but unfortunately i am still struggling to achieve the final goal.
My code so far :
import win32com
from win32com.client import Dispatch
import codecs
import re
import json
# Login Credentials
qcServer = "https://almurl.saas.microfocus.com/qcbin/"
qcUser = "my_username"
qcPassword = "pwd"
qcDomain = "domain"
testList = []
testdict = {}
project = "Crew_Management"
# Do the actual login
td = win32com.client.Dispatch("TDApiOle80.TDConnection.1")
td.InitConnectionEx(qcServer)
td.Login(qcUser,qcPassword)
td.Connect(qcDomain,project)
if td.Connected == True:
print ("System: Logged in to " +project)
else:
print ("Connect failed to " +project)
mg = td.TreeManager # Tree manager
name = ['TC001','TC002','TC003','TC003','TC004','TC005','TC006','TC007','TC008','TC009','TC010','TC011','TC012','TC013','TC014']
folder = mg.NodeByPath('Subject\\Test Factory\\MPG\\MPG Regression Test_Yearly Request\\GUI')
for x in name:
testList = folder.FindTests(x)
#print(type(testList))
print(testList[0].Name)
print(testList[0].DesStepsNum)
td.Disconnect()
td.Logout()
Any help or guidance is much appreciated !
Assuming that you have working experience in Python. Here I am writing all the different functions needed to complete your task.
Reference: https://admhelp.microfocus.com/alm/api_refs/REST_TECH_PREVIEW/ALM_REST_API_TP.html
Global Variable
import re
import json
import datetime
import time
import sys
import os, fnmatch
from os import listdir
from os.path import isfile, join
from xml.etree.ElementTree import Element, SubElement, tostring, parse
import glob
from requests.auth import HTTPBasicAuth
import requests
ALM_USER_NAME = ""
ALM_PASSWORD = ""
ALM_DOMAIN = ""
ALM_URL = ""
AUTH_END_POINT = ALM_URL + "authentication-point/authenticate"
QC_SESSION_END_POINT = ALM_URL + "rest/site-session"
QC_LOGOUT_END_POINT = ALM_URL + "authentication-point/logout"
ALM_MIDPOINT = "rest/domains/" + ALM_DOMAIN + "/projects/"
PATH_SEP = os.path.sep
Login Function
def alm_login(self):
"""
Function : alm_login
Description : Authenticate user
Parameters : global parameter
alm_username - ALM User
alm_password - ALM Password
"""
response = self.alm_session.post(AUTH_END_POINT,
auth=HTTPBasicAuth(ALM_USER_NAME, ALM_PASSWORD))
if response.status_code == 200:
response = self.alm_session.post(QC_SESSION_END_POINT)
if response.status_code == 200 | response.status_code == 201:
print "ALM Authentication successful"
else:
print "Error: ", response.staus_code
else:
print "Error: ", response.staus_code
self.alm_session.headers.update({'Accept':'application/json',
'Content-Type': 'application/xml'})
return
Logout Function
After the logout method is successful the cookie should expire
def alm_logout(self):
'''
Function : alm_logout
Description : terminate user session
Parameters : No Parameters
'''
response = self.alm_session.post(QC_LOGOUT_END_POINT)
print "Logout successful", response.headers.get('Expires'), response.status_code
return
Get Test Set Folder
If the test cases span across multiple test suites then it is better to get the test set folder first and find the necessary test suite.
def find_test_set_folder(self):
'''
Function : find_test_set_folder
Description : This sends a couple of http request and authenticate the user
Parameters : 1 Parameter
test_set_path - ALM test set path
'''
json_str = json.loads(self.find_folder_id(self.test_set_path.split("\\"), "test-set-folders"
, 0, "id"))
if 'entities' in json_str:
return create_key_value(json_str['entities'][0]['Fields'])['id']
else:
return create_key_value(json_str['Fields'])['id']
Get Folder Id
This method will help you find the Test Suite Folder ID or Test Plan Folder Id.
def find_folder_id(self, arrfolder, str_api, parent_id, fields):
'''
Function : find_folder_id
Description : This sends a couple of http request and authenticate the user
Parameters : 1 Parameter
test_set_path - ALM test set path
'''
for foldername in arrfolder:
payload = {"query": "{name['" + foldername + "'];parent-id[" + str(parent_id) + "]}",
"fields": fields}
response = self.alm_session.get(ALM_URL + ALM_MIDPOINT + "/" + str_api, params=payload)
obj = json.loads(response.text)
if obj["TotalResults"] >= 1:
parent_id = get_field_value(obj['entities'][0]['Fields'], "id")
# print("folder id of " + foldername + " is " + str(parent_id))
else:
# print("Folder " + foldername + " does not exists")
inputdata = dict()
inputdata['Type'] = str_api[0:len(str_api) - 1]
inputdata['name'] = foldername
inputdata['parent-id'] = str(parent_id)
data = generate_xml_data(inputdata)
response = self.alm_session.post(ALM_URL + ALM_MIDPOINT + "/" + str_api, data=data)
obj = json.loads(response.text)
if response.status_code == 200 | response.status_code == 201:
parent_id = get_field_value(obj['Fields'], "id")
# print("folder id of " + foldername + " is " + str(parent_id))
return response.text
Create Run Instance
Before updating the testing status, we must create a run instance for the test.
def create_run_instance(self, test_set_id, test_map):
'''
Function : create_run_instance
Description : Create new run instances
Parameters : Test Set Id
'''
str_api = "test-instances"
fields = "id,test-id,test-config-id,cycle-id"
payload = {"query": "{cycle-id['" + test_set_id + "']}", "fields": fields,
"page-size": 5000}
response = self.alm_session.get(ALM_URL + ALM_MIDPOINT + "/" + str_api, params=payload)
obj = json.loads(response.text)
run_instance_post = "<Entities>"
for entity in obj["entities"]:
run_name = re.sub('[-:]', '_',
'automation_' + datetime.datetime.fromtimestamp(time.time()).strftime(
'%Y-%m-%d %H:%M:%S'))
temp_map = create_key_value(entity["Fields"])
_test_id = int(temp_map['test-id'])
self.parser_temp_dic[_test_id]['testcycl-id'] = temp_map['id']
self.parser_temp_dic[_test_id]['test-config-id'] = temp_map['test-config-id']
self.parser_temp_dic[_test_id]['test-id'] = temp_map['test-id']
self.parser_temp_dic[_test_id]['cycle-id'] = temp_map['cycle-id']
# parser_temp_dic[int(temp_map['test-id'])]['status'].sort()
status = "Passed"
if 'Failed' in self.parser_temp_dic[int(temp_map['test-id'])]['status']:
status = 'Failed'
self.parser_temp_dic[int(temp_map['test-id'])]['final-status'] = status
inputdata = dict()
inputdata['Type'] = 'run'
inputdata['name'] = run_name
inputdata['owner'] = ALM_USER_NAME
inputdata['test-instance'] = str(1)
inputdata['testcycl-id'] = str(temp_map['id'])
inputdata['cycle-id'] = str(temp_map['cycle-id'])
inputdata['status'] = 'Not Completed'
inputdata['test-id'] = temp_map['test-id']
inputdata['subtype-id'] = 'hp.qc.run.MANUAL'
data = generate_xml_data(inputdata)
run_instance_post = run_instance_post + data
self.bulk_operation("runs", run_instance_post + "</Entities>", True, "POST")
return
Update Run Instance
def update_run_instance(self, test_set_id):
'''
Function : update_run_instance
Description : Update the test status in run instances
Parameters : No input parameter
'''
fields = "id,test-id"
payload = {"query": "{cycle-id['" + test_set_id + "']}", "fields": fields,
"page-size": 5000}
response = self.alm_session.get(ALM_URL + ALM_MIDPOINT + "/runs", params=payload)
obj = json.loads(response.text)
run_instance_put = "<Entities>"
for entity in obj["entities"]:
if len(entity["Fields"]) != 1:
temp_map = create_key_value(entity["Fields"])
self.parser_temp_dic[int(temp_map['test-id'])]['run-id'] = temp_map['id']
inputdata = dict()
inputdata['Type'] = 'run'
inputdata['id'] = str(temp_map['id'])
intermediate_ = self.parser_temp_dic[int(temp_map['test-id'])]['testcycl-id']
inputdata['testcycl-id'] = str(intermediate_)
inputdata['status'] = self.parser_temp_dic[int(temp_map['test-id'])]['final-status']
data = generate_xml_data(inputdata)
run_instance_put = run_instance_put + data
self.bulk_operation("runs", run_instance_put + "</Entities>", True, "PUT")
return
Upload Result File
Uploading file to any object in ALM
def upload_result_file(self, test_set_id, report_file):
'''
Function : upload_result_file
Description : Upload test result to ALM
'''
payload = open(report_file, 'rb')
headers = {}
headers['Content-Type'] = "application/octet-stream"
headers['slug'] = "test-results" + report_file[report_file.rfind(".")+1: ]
response = self.alm_session.post(ALM_URL + ALM_MIDPOINT + "/test-sets/" +
str(test_set_id) + "/attachments/",
headers=headers, data=payload)
if not (response.status_code == 200 or response.status_code == 201):
print "Attachment step failed!", response.text, response.url, response.status_code
return
Bulk Operation
This is a helper that allows us to POST an array of data.
def bulk_operation(self, str_api, data, isbulk, request_type):
'''
Function : Post Test Case / Test Instance
Description : Generic function to post multiple entities.
Parameters : 3 parameters
str_api - End point name
data - Actual data to post
isbulk - True or False
'''
response = None
headers = {}
try:
if isbulk:
headers['Content-Type'] = "application/xml;type = collection"
if request_type == 'POST':
response = self.alm_session.post(ALM_URL + ALM_MIDPOINT + "/" + str_api, data=data,
headers=headers)
elif request_type == 'PUT':
response = self.alm_session.put(ALM_URL + ALM_MIDPOINT + "/" + str_api, data=data,
headers=headers)
except Exception as err:
print err
if response.status_code == 200 | response.status_code == 201:
return response.text
return response
You can refer this code
https://github.com/arunprabusamy/Python-Libraries/blob/main/alm_RestAPI/almLib.py
You need to send only three values - Test Set ID (Cycle ID), ALM Test ID & Execution Status. The library automatically builds the json payload and creates a test run and update result.

How to pass a parameter as string which include special character in flask app route

I want to pass "top3/1" as parameter in url. but it return 404 error.
here is my code:
#APP.route('/get_agent_details_on_voucher_code/<string:code>',methods=['GET'])
def get_agent_details_on_voucher_code(code):
result = []
if code == 'TOP3':
voucher_earning_list = [{'voucher_code':'TOP3/1','agent_id':12345,'voucher_id':8}]
if len(voucher_earning_list)>0:
for item in voucher_earning_list:
get_details = requests.get('http://192.168.1.55:5000/get_agent_details/'+str(item['agent_id']))
get_result = get_details.json()
if len(get_result) > 0:
get_ag_mobileno = get_result[0]['mobile']
result.append({'mobile_no':get_ag_mobileno,'agent_id':item['agent_id'],'voucher_id':item['voucher_id']})
response = jsonify(result)
else:
response = jsonify(result)
else:
response = jsonify(result)
else:
response = jsonify(result)
return response
That's a tricky question: generally with flask you have to specify the routes up to the final endpoint.
If you want to match all the sub routes you can use the type path instead of string, os you just need to change the route into:
#APP.route('/get_agent_details_on_voucher_code/<path:code>',methods=['GET'])
In this way you will obtain all the sub routes of /get_agent_details_on_voucher_code/, keep in mind the code will be a string, you have to extract the information you need parsing it.

I want to save the results of running Python to a file [duplicate]

This question already has answers here:
How to redirect 'print' output to a file?
(15 answers)
Closed 4 years ago.
import requests, json, pprint
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
pagesize = 1000
api_url_base = "https://test/sepm/api/v1/"
authentication_url = "https://test/sepm/api/v1/identity/authenticate"
json_format = True
payload = {
"username" : "test",
"password" : "test",
"domain" : ""}
headers = {"Content-Type":"application/json"}
r = requests.post(authentication_url, verify=False, headers=headers,
data=json.dumps(payload))
api_token = (r.json()["token"])
headers = {'Content-Type': 'application/json', 'Authorization': 'Bearer
{0}'.format(api_token)}
def get_info(url,params):
api_url = url
params = params
response = requests.get(api_url, headers=headers,verify=False,
params=params)
if response.status_code == 200:
return json.loads(response.content.decode('utf-8'))
else:
return response.status_code
def aggregate(endpoint_info,numberOfElements):
itr =0
while itr <= (numberOfElements-1):
computerName=endpoints_info['content'][itr]['computerName']
ipAddresses=endpoints_info['content'][itr]['ipAddresses'][0]
logonUserName=endpoints_info['content'][itr]['logonUserName']
lastUpdateTime=endpoints_info['content'][itr]['creationTime']
agentVersion = endpoints_info['content'][itr]['agentVersion']
print(computerName, ipAddresses, logonUserName, lastUpdateTime, a
gentVersion)
itr = itr+1
groups_url = '{0}groups'.format(api_url_base)
fingerprint_url = '{0}policy-objects/fingerprints'.format(api_url_base)
endpoints_url = '{0}computers?'.format(api_url_base)
total_pages = get_info(endpoints_url,{'pageSize':pagesize})['totalPages']
itr = 1
while itr <= total_pages:
params = {'pageSize':pagesize, 'pageIndex':itr}
endpoints_info = get_info(endpoints_url,params)
numberOfElements = endpoints_info['numberOfElements']
itr = itr +1
if endpoints_info is not 200:
aggregate(endpoints_info,numberOfElements)
else:
print('[!] Request Failed, {0}')
This is the code that uses the Symantec rest API.
When you run this
You can get the result of the list format as shown below.
commnad line output
P09PC 123.63.40.37 test-9 1520236609428 14.0.3897.1101
P10PC 123.63.40.31 test-10 1520230270130 14.0.3775.1002
P11PC 123.63.40.27 test-11 1520229680645 14.0.3775.1002
P12PC 123.63.40.26 test-12 1520229515250 14.0.3775.1002
I modified this source and I want to save the results to a file.
Unfortunately, the effort failed for several days.
Tell me how to save it as a file
Do you mean instead of printing on terminal you want to write it on a file?
The process is simple, just open a file in desired mode (append mode or write mode depending on your use case) and simply write it there.
Consider reading this tutorial for a grasp over the concept.
After initializing the file object (as described in the tutorial) you just need to write in the file instead of print statements. The code will look something like this
file = open('output.txt', 'w')
file.write(computerName +' '+ ipAddresses +' '+ logonUserName +' '+ lastUpdateTime +' '+ agentVersion)
file.close()

Categories

Resources