I wrote this server code:
from bottle import run, route, get, post, request, template
import json
import socket
import os
import time
#route('/')
#route('/RegisterMessage/<message_type>', method='GET')
def reg_msg_type(message_type):
print "Suscribe to", message_type, 'messages'
if message_type == 'time':
time = dict()
time['utc_time'] = 123456
time['time_zone'] = -120
return time
#configuring host, port.
run(host='192.168.0.119', port=8088, debug=True)
When I go to http://192.168.0.119:8088/RegisterMessage/time in my browser, I get this response:
{"time_zone": -120, "utc_time":123456}
Now I want to write a client in python which will retrieve those values from my server. I am unable to find anything related to this in the documentation for bottle.
Related
I 'm trying to write a code which will send a json file from a flask server to chregraphe in order to program a NAO robot. I want to parse a random number from 1 to 3 and NAO say the number accordingly. Unfortunately i haven't managed to do it.
The code that i use to send the number from flask server is
import http.client
import json
import random
from flask import Flask, request
app = Flask(__name__)
#app.route('/')
def index():
IP = "10.0.0.23" # The IP address of my robot
PORT = 9559
number = random.randint(1, 3)
data = json.dumps({"number": number})
# Connect to Choregraphe
conn = http.client.HTTPConnection(IP, PORT)
# Send the data to Choregraphe
headers = { "Content-Type": "application/json" }
conn.request("POST", "/module/ALMemory/value/ExampleKey", data, headers)
return "Data sent to Choregraphe: " + data
if __name__ == '__main__':
app.run()
I'm trying to send the number to the "Examplekey"
Also i use a python script box in choregraph with the beneath code
def onInput_onStart(self, p):
# Connect to ALMemory
memory = ALProxy("ALMemory")
# Read the value stored under the key "ExampleKey"
data = memory.getData("ExampleKey")
# Parse the JSON string into a dictionary
data = json.loads(data)
# Get the "number" value from the dictionary
number = data["number"]
if number == 1:
text = "one"
elif number == 2:
text = "two"
else
text = "three"
tts = ALProxy("ALTextToSpeech", "10.0.0.23", 9559)
tts.say(text)
Welcome Tolis to StackOverflow!
While it might be starting a Flask server, your first snippet of code seems rather focused on sending an HTTP request to http://10.0.0.23:9559, where I suppose NAOqi is listening to - and NAOqi does not "speak" HTTP, it speaks Qi.
If you want to send data via HTTP, you will need to get a Flask server running on the robot, and call the relevant NAOqi APIs in response.
But bringing Flask to the robot (via Choregraphe) is no easy task. Instead I would recommend that your client code directly uses the Python SDK for NAOqi 2.5 (better for Python 2.x) or libQi Python (better for Python 3.x).
The client code would look like this (not tested):
import qi
if __name__ == "__main__":
app = qi.Application(sys.argv)
app.start()
memory = session.service("ALMemory")
number = random.randint(1, 3)
service.setData("ExampleKey", number)
Actually i have a python script and soap server running using soap spyne and i need to call that soap api using c++ gsoap client so that the python script will run and get the output as a response to client
i am able to call the api using SOAP UI and python zeep client but when i try to call the client using gsoap it gave me error
DEBUG:spyne.protocol.soap.soap11:ValueError: Deserializing from unicode strings with encoding declaration is not supported by lxml
the generated wsdl file of both gsoap and soap spyne have different namespace also
```python
from spyne import Application, rpc, ServiceBase, Integer, Unicode,String
from spyne.protocol.soap import Soap11
from spyne.server.wsgi import WsgiApplication
from spyne.model.complex import ComplexModel
from spyne.model.complex import Array
from twisted.internet import reactor
from twisted.web.server import Site
from twisted.web.wsgi import WSGIResource
from twisted.python import log
import sys
sys.path.insert(1,'../cloud-client/slicing')
import speech as t
class caps__CSoapReqBuf(ComplexModel):
stringarray=String
size=Integer
class caps__CSoapResponse(ComplexModel):
__namespace__ = "spyne.examples.hello.soap"
nRetCode=Integer
strResponseData=String
class caps__CSoapRequest(ComplexModel):
__namespace__ = "spyne.examples.hello.soap"
nRequestType = Integer
wstrRequestParam= String
class caps_CCallbackData(ComplexModel):
__namespace__ = "spyne.examples.hello.soap"
nPort=Integer
strFunction = String
class TranscriptionService(ServiceBase):
#rpc(String, String, caps_CCallbackData, caps__CSoapResponse, _returns=Integer)
def caps__SoapRequestString(ctx, function_name, SoapRequest, CallbackData, SoapResponse):
parameters = SoapRequest
list = parameters.split('|')
d = dict(s.split(':') for s in list)
filename = d['path']
samplerate = int(d['sr'])
outputpath = d['outputpath']
# samplerate=parameters.samplerate
if(function_name=='gettranscription'):
print("gettranscription")
out=t.main(filename,samplerate)
SoapResponse.nRetCode=1
SoapResponse.wstrResponseData=out
return 0
elif(function_name=='getocr'):
return "Do OCR"
else:
return "error"
#rpc(caps__CSoapResponse,_returns=Unicode)
def caps_SoapResponseString(ctx,caps__CSoapResponse):
response = caps__CSoapResponse.wstrResponseData
return response
application = Application([TranscriptionService], 'spyne.examples.hello.soap',
in_protocol=Soap11(validator='lxml'),
out_protocol=Soap11())
wsgi_application = WsgiApplication(application)
if __name__ == '__main__':
import logging
from wsgiref.simple_server import make_server
ip = '192.168.0.103'
port = 8090
resource = WSGIResource(reactor, reactor, wsgi_application)
site = Site(resource)
reactor.listenTCP(port, site,interface=ip)
logging.basicConfig(level=logging.DEBUG)
logging.getLogger('spyne.protocol.xml').setLevel(logging.DEBUG)
logging.info("listening to "+ ip +":"+str(port))
reactor.run()
```
Updated
After updating the code following errors follows in response.
``` Response
'<soap11env:Envelope
xmlns:soap11env="http://schemas.xmlsoap.org/soap/envelope/">\n
<soap11env:Body>\n <soap11env:Fault>\n
<faultcode>soap11env:Client.ResourceNotFound</faultcode>\n
<faultstring>Requested resource
\'{http://tempuri.org/caps.xsd/Service.wsdl}\' not
found</faultstring>\n <faultactor></faultactor>\n
</soap11env:Fault>\n </soap11env:Body>\n</soap11env:Envelope>\n'
DEBUG:spyne:gc.collect() took around 40ms.
```
On that front, lxml is a bit strict on the kind of stream it thinks it can process.
I'm persuaded that the right thing to do to solve this conflict is to strip the encoding declaration from the xml string.
You can add a handler for the 'wsgi_call' event to implement this. See the events example to see what the relevant API looks like.
My solution to this is to let lxml fail and parse the payload manually using WebOb and then place it in the user defined context. You can later access ctx.udc to access the data. So:
...
from webob import Request as WebObRequest
...
HOST = '0.0.0.0'
PORT = 8000
# parse payload manually
def _on_wsgi_call(ctx):
req = WebObRequest(ctx.transport.req)
decoded = req.body.decode('utf-8')
envelope = Etree.fromstring(decoded)
# depending on your data, you may need to update this step
element = next(envelope.iter())
ctx.udc = element.text
if __name__ == '__main__':
application = initialize([YourService])
wsgi_application = WsgiApplication(application)
wsgi_application.event_manager.add_listener('wsgi_call', _on_wsgi_call)
resource = WSGIResource(reactor, reactor, wsgi_application)
site = Site(resource)
reactor.listenTCP(PORT, site, interface=HOST)
logging.info('listening on: %s:%d' % (HOST, PORT))
logging.info('wsdl is at: http://%s:%d/?wsdl' % (HOST, PORT))
sys.exit(reactor.run())
I am trying to send a python dictionary created from client.py to my webservice, have the webservice do something to the data, and return a boolean to client.py. This is the code I have so far for the server and client:
Server side (inside webservice.py):
from flask import Flask
from flask import request
import json
app = Flask(__name__)
#app.route('/determine_escalation',methods = ['POST'])
def determine_escalation():
jsondata = request.form['jsondata']
data = json.loads(jsondata)
#stuff happens here that involves data to obtain a result
result = {'escalate':'True'}
return json.dumps(result)
if __name__ == '__main__':
app.run(debug=True)
Client side (inside client.py):
import sys
import json
import requests
conv = [{'input': 'hi', 'topic': 'Greeting'}]
s = json.dumps(conv)
res = requests.post("http://127.0.0.1:5000/determine_escalation",data=s)
print res.text
But when I print out res.text, I get this:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>400 Bad Request</title>
<h1>Bad Request</h1>
<p>The browser (or proxy) sent a request that this server could not understand.</p>
What am I doing wrong, and how can I fix this? New to Flask and JSON stuff so any help is appreciated.
OK - a few issues here:
First, you can use requests.get_json() to retrieve your JSON data at the server end:
from flask import Flask
from flask import request
import json
app = Flask(__name__)
#app.route('/determine_escalation/', methods = ['POST'])
def determine_escalation():
jsondata = request.get_json()
data = json.loads(jsondata)
#stuff happens here that involves data to obtain a result
result = {'escalate': True}
return json.dumps(result)
if __name__ == '__main__':
app.run(debug=True)
Also, when you are putting your data together, rather than using "data=s" to send the request, use "json=s":
import sys
import json
import requests
conv = [{'input': 'hi', 'topic': 'Greeting'}]
s = json.dumps(conv)
res = requests.post("http://127.0.0.1:5000/determine_escalation/", json=s).json()
print(res['escalate'])
Please note that I have added trailing slashes at the end of the URL - this is just good practice :-)
I've also incorporated MarcelK's suggested changes - removing the quotes from the boolean 'True' (server side) and using .json() to parse the response on the client side - both of these are great suggestions.
I've tested this revised version (and re-revised version) and it works fine.
I have a python program that I run as a Windows service (built with py2exe).
My python program imports 'bottle.py' and handles various Restful api requests.
When I fire requests at my service at the rate of one every 50 millseconds, eventually my python program stops responding after about 2000 requests, and after approximately 20 seconds, returns the HTTP response message "read timeout".
I should add here, that on receiving a Restful API request, I simply send a response back. Anything meaningful has been commented out.
When I run the python program as a regular Windows executable (i.e. not a Windows service), I do not see this problem.
Does anyone know if this is to do with bottle?
How best to debug this?
Below is the file restapi.py:
import json
import logging
from bottle import route, run
from bottle import get, post, delete
from bottle import request
from bottle import KillableWSGIRefServer
logger = logging.getLogger('RestAPI')
def _create_response(command, status):
logger.info('_create_response() Enter')
return '''<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<response>
<command>''' + command + '''</command>
<statuscode>''' + str(status) + '''</statuscode>
</response>'''
def _create_json_response(command, status):
logger.info('_create_response() Enter')
return {"command" : command, "status" : status}
#route('/openapi/hello', method='POST')
def _hello():
return _create_response("hello",0)
#route('/openapi/start', method='POST')
def _start():
logger.info('_start() Enter')
return _create_response("start",0)
#route('/openapi/multicheckin', method='POST')
def _multicheckin():
logger.info('_multicheckin() Enter')
return _create_response("multicheckin",0)
#route('/openapi/multicheckout', method='POST')
def _multicheckout():
logger.info('_multicheckout() Enter')
return _create_response("multicheckout",0)
def start(host, port):
logger.info('start() Enter')
global myServer
myServer = KillableWSGIRefServer(host=host, port=port)
run(server=myServer)
def stop():
logger.info('stop() Enter')
myServer.stop()
The RestAPI start() function is called form another module via:
restapi.start(self.host, self.port)
Below I provided a code example which simply respond to HTTP GET request with the data from Redis:
Request: http://example.com:8888/?auth=zefDWDd5mS7mcbfoDbDDf4eVAKb1nlDmzLwcmhDOeUc
Response: get: u'"True"'
The purpose of this code is to serve as a REST server (that's why I'm using lazyConnectionPool) responding to the requests, and using data from Redis (read/ write).
What I need to do:
Run multiple requests to Redis inside render_GET of the IndexHandler (like GET, HMGET, SET, etc)
Run multiple requests in a transaction inside render_GET of the IndexHandler
I've tried multiple ways to do that (including examples from the txredisapi library), but due to lack of experience failed to do that. Could you please advise on questions 1) and 2).
Thanks in advance.
import txredisapi as redis
from twisted.application import internet
from twisted.application import service
from twisted.web import server
from twisted.web.resource import Resource
class Root(Resource):
isLeaf = False
class BaseHandler(object):
isLeaf = True
def __init__(self, db):
self.db = db
Resource.__init__(self)
class IndexHandler(BaseHandler, Resource):
def _success(self, value, request, message):
request.write(message % repr(value))
request.finish()
def _failure(self, error, request, message):
request.write(message % str(error))
request.finish()
def render_GET(self, request):
try:
auth = request.args["auth"][0]
except:
request.setResponseCode(404, "not found")
return ""
d = self.db.hget(auth, 'user_add')
d.addCallback(self._success, request, "get: %s\n")
d.addErrback(self._failure, request, "get failed: %s\n")
return server.NOT_DONE_YET
# Redis connection parameters
REDIS_HOST = '10.10.0.110'
REDIS_PORT = 6379
REDIS_DB = 1
REDIS_POOL_SIZE = 1
REDIS_RECONNECT = True
# redis connection
_db = redis.lazyConnectionPool(REDIS_HOST, REDIS_PORT, REDIS_DB, REDIS_POOL_SIZE)
# http resources
root = Root()
root.putChild("", IndexHandler(_db))
application = service.Application("web")
srv = internet.TCPServer(8888, server.Site(root), interface="127.0.0.1")
srv.setServiceParent(application)
Regarding first question:
There is a few ways to generalize to making multiple database requests in a single HTTP request.
For example you can make multiple requests:
d1 = self.db.hget(auth, 'user_add')
d2 = self.db.get('foo')
Then you can get a callback to trigger when all of these simultaneous requests are finished (see twisted.internet.defer.DeferredList).
Or you can use inlineCallbacks if you need sequential requests. For example:
#inlineCallbacks
def do_redis(self):
foo = yield self.db.get('somekey')
bar = yield self.db.hget(foo, 'bar') # Get 'bar' field of hash foo
But you will need to read more about combining inlineCallbacks with twisted.web (there are SO questions on that topic you should look up).
Regarding question 2:
Transactions are really ugly to do without using inlineCallbacks. There is an example at txredisapi homepage that shows it using inlineCallbacks.