I've just begun my journey into the realms of the CherryPy module in Python. It's pretty awesome how easy it makes it to setup a server with a RESTful api, however I've ran into an issue. My code is only acknowledging the first parameter in a query string.
I want to make a GET request like so:
curl -X GET 127.0.0.1:8080/api/sum/?a=2&b=3
My Python code is as follows:
import cherrypy
class getSum:
exposed = True
def GET(self, **params):
a = float(params['a'])
b = float(params['b'])
return a+b
if __name__ == '__main__':
cherrypy.tree.mount(getSum(), '/api/sum/', {'/': {'request.dispatch': cherrypy.dispatch.MethodDispatcher()}})
cherrypy.engine.start()
cherrypy.engine.block()
After fiddling with the code for a while I've come to the following diagnosis:
When the query string is being read into params, instead of starting a new entry in the dictionary when it reaches the '&' it just stops instead.
Has anyone got any advice on how to read multiple parameters in as a single query string?
With Thanks, Sean.
The Python script posted in my question is actually a working implementation of what I wanted to do. The problem was instead with the curl request that I was making.
The '&' character in my curl request was truncating my bash command, resulting in this: curl -X GET 127.0.0.1:8080/api/sum/?a=2
The fix for this is to wrap my url in quotes like so: curl -X GET "127.0.0.1:8080/api/sum/?a=2&b=3"
When executing this command 5.0 is returned to the terminal, as expected.
This following post contains a useful discussion on the use of ampersands in curl requests: How to include an '&' character in a bash curl statement
Related
I am working through the Node.js The Right Way book by Jim Wilson. I am currently trying to use a PUSH request to create a new bundle with the specified name.
* curl -X POST http://:/api/bundle?name=
However, when I use the command:
$ curl -s -X POST localhost:60702/api/bundle?name=light%20reading | jq '.'
rather than getting the JSON indicating that a Bundle has been created, I get: zsh: no matches found: localhost:60702/api/bundle?name=light%20reading
The command should be using a POST request to create a new All of my code is bit for bit identical to the code listed in the book. Any ideas?
Can you try
curl -s -X POST 'localhost:3000/api/bundle?name=light%20reading'
i.e wrap the url within '
This seems to be an issue with zsh solved here.
There are several ways to solve this:
You can escape the question mark ? in the url by quoting the url as explained by #huzaifa-saifuddin to avoid zsh treating it as a wildcard character.
As explained here, you can create an alias for curl: alias curl='noglob curl'
As explained here, you can disable to nomatch handling by adding the following to your ~/.zshrc: unsetopt nomatch
I am trying to get an API query into python. The command line
curl -X POST https://xxxx.com/api/auth/refreshToken -d access_token
it will give output in text string.access_tokenis a hexadecimal variable that remains constant throughout. I would like to make this call from python so that I can loop through different ids and analyze the output. Any ideas?
Many thanks.
You can use requests library https://2.python-requests.org/en/master/user/quickstart/#make-a-request
Maybe something like this :
response = requests.post('https://httpbin.org/post', data = {'key':'value'})
Then you can utilise the response and process it
I'm trying to imitate the following cURL command to POST my url-encoded list to a form:
curl "https://website.com/update/" --data "simChangesList=%5B%7B%22simId%22%3A760590802%2C%22changeType%22%3A2%2C%22targetValue%22%3A%220003077%22%2C%22effectiveDate%22%3Anull%7D%5D" --compressed
The data I need to url-encode is the simChangesList. Essentially, this data is decoded as simChangesList: [{"simId":760590802,"changeType":2,"targetValue":000307,"effectiveDate":null}]
With the following script, I come across a Required List parameter 'simChangesList' is not present error.
Here's my script:
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
enc = urllib.quote('simChangesList: [{"simId":760590802,"changeType":2,"targetValue":000307,"effectiveDate":null}]')
auth = session.post(uri, data=enc, headers=headers)
print auth.text
However, executing the above script returns the above missing list parameter error.
How can I pass in the missing list parameter when my encoded list looks like this:
simChangesList%3A%20%5B%7B%22simId%22%3A760590802%2C%22changeType%22%3A2%2C%22targetValue%22%3A000307%2C%22effectiveDate%22%3Anull%7D%5D
Notice it's missing the '=' operator, why can I not execute my script and make it closely resemble my cURL command to post my url-encoded information?
I also encountered a similar situation landlord, but I just prompted one of the parameters inside json does not exist, is looking for a solution.
On the landlord to pass parameters, it is recommended to add a json.dumps (data)
try it.
I'm trying to send two parameters to a URL routed with Flask.
If I do:
curl -i http://127.0.0.1:5000/api/journeys/count?startStationName=Hansard%20Mews,%20Shepherds%20Bush&endStationName=Farringdon%20Lane,%20Clerkenwell
Then my code which is:
#application.route('/api/journeys/count', methods=['GET'])
def journeys():
print request.args
startStationName = request.args.get('startStationName')
endStationName = request.args.get('endStationName')
Should print a dict with startStationName and endStationName defined.
However, instead, only the first parameter seems to be received:
ImmutableMultiDict([('startStationName', u'Hansard Mews, Shepherds Bush')])
Anybody got any idea what I'm doing wrong? I have a feeling there must be some kind of stupid mistake or misunderstanding somewhere but I've been looking for an hour and can't find it.
Your shell interprets the & as a put the command in the background character. To prevent this, quote the whole URL:
curl -i "http://127.0.0.1:5000/api/journeys/count?startStationName=Hansard%20Mews,%20Shepherds%20Bush&endStationName=Farringdon%20Lane,%20Clerkenwell"
I'm trying to pass information to a python page via the url. I have the following link text:
"<a href='complete?id=%s'>" % (str(r[0]))
on the complete page, I have this:
import cgi
def complete():
form = cgi.FieldStorage()
db = MySQLdb.connect(user="", passwd="", db="todo")
c = db.cursor()
c.execute("delete from tasks where id =" + str(form["id"]))
return "<html><center>Task completed! Click <a href='/chris'>here</a> to go back!</center></html>"
The problem is that when i go to the complete page, i get a key error on "id". Does anyone know how to fix this?
EDIT
when i run cgi.test() it gives me nothing
I think something is wrong with the way i'm using the url because its not getting passed through.
its basically localhost/chris/complete?id=1
/chris/ is a folder and complete is a function within index.py
Am i formatting the url the wrong way?
The error means that form["id"] failed to find the key "id" in cgi.FieldStorage().
To test what keys are in the called URL, use cgi.test():
cgi.test()
Robust test CGI script, usable as main program. Writes minimal HTTP headers and formats all information provided to the script in HTML form.
EDIT: a basic test script (using the python cgi module with Linux path) is only 3 lines. Make sure you know how to run it on your system, then call it from a browser to check arguments are seen on the CGI side. You may also want to add traceback formatting with import cgitb; cgitb.enable().
#!/usr/bin/python
import cgi
cgi.test()
Have you tried printing out the value of form to make sure you're getting what you think you're getting? You do have a little problem with your code though... you should be doing form["id"].value to get the value of the item from FieldStorage. Another alternative is to just do it yourself, like so:
import os
import cgi
query_string = os.environ.get("QUERY_STRING", "")
form = cgi.parse_qs(query_string)
This should result in something like this:
{'id': ['123']}
First off, you should make dictionary lookups via
possibly_none = my_dict.get( "key_name" )
Because this assigns None to the variable, if the key is not in the dict. You can then use the
if key is not None:
do_stuff
idiom (yes, I'm a fan of null checks and defensive programming in general...). The python documentation suggests something along these lines as well.
Without digging into the code too much, I think you should reference
form.get( 'id' ).value
in order to extract the data you seem to be asking for.