I am trying to write a web service that performs some data processing. The requests contain a data vector as a binary file, and meta-data and processing parameters as form data. An example using python with requests:
import numpy as np
import requests
url = 'http://localhost:8080/pp'
payload = {'param_a': 4, 'param_b': -2.1}
file = {'binary_data': ('file_name.bin', bytes(np.random.randn(1000))}
r = requests.post(url, data=payload, files=file)
Now on the service side, I have:
import bottle
import numpy as np
@bottle.post('/pp')
def pp():
file_path = '/home/generic_user/howhaveyou.bin'
return_file_path = '/home/generic_user/finethanks.bin'
bin_file = bottle.request.files.get('binary_data')
bin_file.save(file_path, overwrite=True)
param_a = float(bottle.request.forms.get('param_a')
param_b = float(bottle.request.forms.get('param_b')
data_vector = np.fromfile(file_path)
processed_data_vector = (data_vector-param_a)*param_b
processed_data_mean = np.mean(processed_data_vector)
processed_data_samples = len(processed_data_vector)
return_metrics = {'mean': processed_data_mean,
'n_of_samples': processed_data_samples}
with open(return_file_path, 'wb') as return_file:
return_file.write(bytes(processed_data_vector))
return return_metrics, bottle.static_file(return_file_path, '/')
which doesn't quite work. Either of the returns work on their own, but together I get the following response:
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html>
<head>
<title>Error: 500 Internal Server Error</title>
<style type="text/css">
html {background-color: #eee; font-family: sans;}
body {background-color: #fff; border: 1px solid #ddd;
padding: 15px; margin: 15px;}
pre {background-color: #eee; border: 1px solid #ddd; padding: 5px;}
</style>
</head>
<body>
<h1>Error: 500 Internal Server Error</h1>
<p>Sorry, the requested URL <tt>'http://localhost:8080/pp'</tt>
caused an error:</p>
<pre>Unsupported response type: <class 'dict'></pre>
</body>
</html>
I have a complete lack of experience with Web Services, so I don't even know if I'm on the right track at all. The point is I wish to return some binary data, along with a few (preferably named) metrics of said data. Is it possible to do this using bottle only? Is there a best practice (with respect to web services, python or both) that I should follow when it comes to this kind of thing?
Note that the client will not be written in python, that is just my test case.
Thanks for any guidance!
The problem with the server-side code is that you cannot return a dictionary (
return_metrics
) and the contents of a file (return_file_path
) with the same response. A solution is to encode the file contents in a string and include it in the returned dict (return_metrics
). Then, the client will need to decode the content string to access the data.