bottle request.json getting a 405 on post - python

I'm trying to get bottle to receive json in an xmlhttprequest and I'm getting a 405 error
Part of my bottle script:
#app.route('/myroute/')
def myroute():
print request.json
Part of my other script to test the xhr out:
jdata = json.dumps({"foo":"bar"})
urllib2.urlopen("http://location/app/myroute/", jdata)
Why am I getting a 405?
bottlepy error: 127.0.0.1 - - [2012-09-23 23:09:34] "POST /myroute/ HTTP/1.0" 405 911 0.005458
urllib2 error: urllib2.HTTPError: HTTP Error 405: Method Not Allowed
I also tried variations of:
#app.route('/myroute/json:json#[1-9]+#')
def myroute(json):
request.content_type = 'application/json'
print request.json, json
Returning json does not seem to be an issue

I think the problem is the server does not allow POST requests. You can probably try sending it in a GET request instead:
urllib2.urlopen("http://location/app/myroute/?" + jdata)
UPDATE:
I just realized, after looking at your question again, that you are actually trying to send JSON data via GET request. You should in general avoid sending JSONs with GET requests, but use POST requests instead[Reference].
To send a POST request to Bottle, you also need to set the headers to application/json:
headers = {}
headers['Content-Type'] = 'application/json'
jdata = json.dumps({"foo":"bar"})
urllib2.urlopen("http://location/app/myroute/", jdata, headers)
Then, with the help of #Anton's answer, you can access the JSON data in your view like this:
#app.post('/myroute/')
def myroute():
print request.json
Also, as a bonus, to send a normal GET request and access it:
# send GET request
urllib2.urlopen("http://location/app/myroute/?myvar=" + "test")
# access it
#app.route('/myroute/')
def myroute():
print request.GET['myvar'] # should print "test"

By default, the route decorator makes the decorated function handle only GET requests. You need to add a method argument to tell Bottle to handle POST requests instead. To do that, you need to change:
#app.route('/myroute/')
to:
#app.route('/myroute/', method='POST')
or a shorter version:
#app.post('/myroute/')

Related

Can't access or print any request data with FastAPI

I have a simple FastAPI endpoint, where I want to receive a string value. In this case, I tried it with a JSON body, but basically it doesn't need to be JSON. I really need only a simple string to separate the requests from each other. Unfortunately, I can't access any of the request parameters with a GET method. I also tried POST method instead, but I get an error:
request:
url = "http://127.0.0.1:5000/ping/"
payload=json.dumps({"key":"test"})
headers = {
"Content-Type": "application/json"
}
response = requests.request("POST", url, headers=headers, json=payload)
print(response.text)
api:
#app.get("/ping/{key}")
async def get_trigger(key: Request):
key = key.json()
test = json.loads(key)
print(test)
test2 = await key.json()
print(key)
print(test2)
return
I can't print anything with post or put:
#app.post("/ping/{key}")
async def get_trigger(key: Request):
...
or
#app.put("/ping/{key}")
async def get_trigger(key: Request):
I get a 405 Method not allowed error.
How can I get this fixed?
The 405 Method Not Allowed status code indicates that "the server knows the request method, but the target resource doesn't support this method". You get this error when you attempt, for instance, to send a POST request to a GET route (as shown in your first example). This, however, is not the only issue with your code (on both client and server sides). Below is given an example on how to achieve what you described in the question using Path parameters. The same could be achieved using Query parameters, as well as Request Body. Please have a look at Python requests documentation on how to specify the parameters/body for each case. I would also highly suggest to take the FastAPI tutorial online—you'll find most of the answers you are looking for there.
app.py
from fastapi import FastAPI
app = FastAPI()
#app.get("/ping/{ping_id}")
async def get_trigger(ping_id: str):
return {"ping_id": ping_id}
test.py
import requests
url = 'http://127.0.0.1:8000/ping/test1'
resp = requests.get(url=url)
print(resp.json())

Trouble getting data from REST http service using requests package

This works fine, I can get data returned:
r = urllib2.Request("http://myServer.com:12345/myAction")
data = json.dumps(q) #q is a python dict
r.add_data(data)
r=urllib2.urlopen(r)
But doing the same with requests package fails:
r=requests.get("http://myServer.com:12345/myAction", data=q)
r.text #This will return a message that says method is not allowed.
It works if I make it a post request: r=requests.post("http://myServer.com:12345/myAction", data=json.dumps(q))
But why?
According to the urllib2.urlopen documentation:
the HTTP request will be a POST instead of a GET when the data parameter is provided.
This way, r=urllib2.urlopen(r) is also making a POST request. That is why your requests.get does not work, but requests.post does.
Set up a session
import session
session = requests.Session()
r = session.get("http://myServer.com:12345/myAction", data=q)
print r.content (<- or could us r.raw)

API Post Python

I am trying to make a post request within the Matchbook API.
I have logged in and I got below "Session- Tocken":
{"session-token":"xxxx_b0b8a6f22a82396b6afcfa344f3022","user-id":xx685,"role":"USER"}
However, I am not sure how to make the post request. See below code used:
headers = {"session-token" : "xxxx_b0b8a6f22a82396b6afcfa344f3022"}
r = requests.post('https://api.matchbook.com/edge/rest/reports/v1/offers/current/?odds-type=DECIMAL&exchange-type=binary&currency=EUR, headers = headers')
print r.text
Below is the error message that I got. It does not make sense to me because I logged in successfully and got the above session-token in response.
{"errors":[{"messages":["You are not authorised to access this resource. Login to continue."]}]}
Am I properly indicating the session-token in the header information of the post request?
You need to pass headers argument in post function.
headers = {"session-token" : "xxxx_b0b8a6f22a82396b6afcfa344f3022"}
response = requests.post('https://api.matchbook.com/edge/rest/reports/v1/offers/current/?odds-type=DECIMAL&exchange-type=binary&currency=EUR', headers=headers)
also if you need to get an json response, just call json() function on response variable.
something like response.json()

Making a successful Python HTTP POST Request

I am trying to write a python script that will make a request to a desktop application listening to 8080 port. The below is the code that I use to make the request.
import requests
payload = {"url":"abcdefghiklmnopqrstuvwxyz=",
"password":"qertyuioplkjhgfdsazxvnm=",
"token":"abcdefghijklmn1254786=="}
headers = {'Content-Type':'application/json'}
r = requests.post('http://localhost:9015/login',params = payload, headers=headers)
response = requests.get("http://localhost:9015/login")
print(r.status_code)
After making the request, I get a response code of 401.
However, when I try the same using the Postman app, I get a successful response. The following are the details I give in Postman:
URL: http://localhost:9015/login
METHOD : POST
Headers: Content-Type:application/json
Body: {"url":"abcdefghiklmnopqrstuvwxyz=",
"password":"qertyuioplkjhgfdsazxvnm=",
"token":"abcdefghijklmn1254786=="}
Can I get some suggestions on where I am going wrong with my python script?
You pass params, when you should pass data, or, even better, json for setting Content-Type automatically. So, it should be:
import json
r = requests.post('http://localhost:9015/login', data=json.dumps(payload), headers=headers)
or
r = requests.post('http://localhost:9015/login', json=payload)
(params adds key-value pairs to query parameters in the url)

how to encode POST data using python's urllib

I'm trying to connect to my Django server using a client side python script. Right now I'm just trying to connect to a view and retrieve the HttpResponse. The following works fine
import urllib2
import urllib
url = "http://localhost:8000/minion/serve"
request = urllib2.Request(url)
response = urllib2.urlopen(request)
html = response.read()
print html
However if I change it to
import urllib2
import urllib
url = "http://localhost:8000/minion/serve"
values = {'name': 'Bob'}
data = urllib.urlencode(values)
request = urllib2.Request(url, data)
response = urllib2.urlopen(request)
html = response.read()
print html
I get urllib2.HTTPError: HTTP Error 500: INTERNAL SERVER ERROR. Am I doing something wrong here? Here are the tutorials I was trying to follow, http://techmalt.com/?p=212 http://docs.python.org/2/howto/urllib2.html.
EDIT: tried to make the following change as per That1Guy's suggestion (other lines left the same)
request = urllib2.Request(url, data)
response = urllib2.urlopen(request, data)
This returned the same error message as before.
EDIT: It seems to work if I change the page I'm viewing so the error isn't in the client side script. So in light of that revelation, here's the server side view that's being accessed:
def serve(request):
return HttpResponse("You've been served!")
As you can see, it's very straight forward.
EDIT: Tested to see if Internal Error might be caused by missing csrf token, but csrf_exempt decorator failed to resolve error.
Finally figured it out with this. How to POST dictionary from python script to django url?
Turns out my url was missing a trailing slash. It's the little things that always get you I guess.

Categories

Resources