Getting 400 Bad Request from Open AI API using Python Flask - flask

I want to get response using Flask from OpenAI API. Whether I am getting Status 400 Bad Request from Browser through http://127.0.0.1:5000/chat
Bad Request
The browser (or proxy) sent a request that this server could not understand.
Also I am checking this from Postman
from flask import Flask, request, render_template
import requests
app = Flask(__name__)
#app.route('/')
def index():
return 'Welcome to ChatGPT app!'
#app.route('/chat', methods=['GET', 'POST'])
def chat():
user_input = request.form['text']
# Use OpenAI's API to generate a response from ChatGPT
response = generate_response_from_chatgpt(user_input)
return response
def generate_response_from_chatgpt(user_input):
api_key = "YOUR_API_KEY"
url = "https://api.openai.com/v1/engines/davinci/completions"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {api_key}"
}
data = {
"prompt": user_input,
"engine": "davinci"
}
response = requests.post(url, headers=headers, json=data)
return response.json()["choices"][0]["text"]
if __name__ == '__main__':
app.run()

It would be best if you check the openai documentation to make sure you are using the correct endpoint and data format in your request.
Also, you should check your API key, if it is correct and if you have reached the limit of requests.
Also, it's worth noting that the code you provided is missing the import statement for Flask. You will need to add the following line at the top of your file:
from flask import Flask, request
Also, I see that you're using request.form['text'] but you should check if the request is a GET or POST request.
if request.method == 'POST':
user_input = request.form['text']
else:
user_input = request.args.get('text')
This is to avoid a KeyError being raised when the request is a GET request.

Related

"Not enough segments" when seding a GET message with Bearer Token Authorization Header (flask_restful + flask_jwt_extended)

I got this error in Flask Application:
curl http://0.0.0.0:8080/ -H "Authorization: Bearer TGazPL9rf3aIftplCYDTGDc8cbTd"
{
"msg": "Not enough segments"
}
Here a sample:
from flask import Flask
from flask_restful import Resource, Api
from flask_jwt_extended import JWTManager, jwt_required
app = Flask(__name__)
jwt = JWTManager(app)
api = Api(app)
class HelloWorld(Resource):
#jwt_required
def get(self):
return {'hello': 'world'}
api.add_resource(HelloWorld, '/')
Console:
* Serving Flask app "app.py" (lazy loading)
* Environment: development
* Debug mode: on
* Running on http://0.0.0.0:8080/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 890-265-009
127.0.0.1 - - [26/Apr/2020 02:02:32] "GET / HTTP/1.1" 422 -
I can't understand: What's wrong?
The exception has been thrown in other lib (line 183 in site-packages/jwt/api_jws.py):
def _load(self, jwt):
if isinstance(jwt, text_type):
jwt = jwt.encode('utf-8')
if not issubclass(type(jwt), binary_type):
raise DecodeError("Invalid token type. Token must be a {0}".format(
binary_type))
try:
signing_input, crypto_segment = jwt.rsplit(b'.', 1)
header_segment, payload_segment = signing_input.split(b'.', 1)
except ValueError:
raise DecodeError('Not enough segments')
The token you are trying to pass in (TGazPL9rf3aIftplCYDTGDc8cbTd)is not a valid JWT. A valid JWT has three segments separated by dots: <base64_encoded_header>.<base64_encoded_payload>.<signature>. You can read more about it here: https://jwt.io/introduction/
I will post here an answer related to my initial problem above, the context is that I was trying to user flask_jwt_extend to use in firebase authentication, but I have this "Not enough segments" errors and I got blocked.
So after that, I change my code to:
from flask import Flask, request
from flask_restful import Resource, Api
from functools import wraps
import google.auth.transport.requests
import google.oauth2.id_token
app = Flask(__name__)
api = Api(app)
HTTP_REQUEST = google.auth.transport.requests.Request()
def jwt_required_gcp(fn):
#wraps(fn)
def wrapper(*args, **kwargs):
id_token = request.headers['Authorization'].split(' ').pop()
claims = google.oauth2.id_token.verify_firebase_token(
id_token, HTTP_REQUEST)
if not claims:
return 'Unauthorized', 401
return fn(*args, **kwargs)
return wrapper
class HelloWorld(Resource):
#jwt_required_gcp
def get(self):
return {'hello': 'world'}
api.add_resource(HelloWorld, '/')
Check your JWT Token. Is it valid?
#fresh_jwt_required - fresh_jwt_required() function to only allow fresh tokens to access the certain endpoint
#jwt_required - A decorator to protect a Flask endpoint with JSON Web Tokens. Any route decorated with this will require a valid JWT to be present in the request (unless optional=True, in which case no JWT is also valid) before the endpoint can be called.
For more detail review flask-jwt-extended

How to fix: "Origin <localhost> is not allowed by Access-Control-Allow-Origin." -- with flask_cors

I have set up a server with flask CORS and had it working for sending data to a React web app that I built, but when I went to test the POST method it stoped working and now it is broken for sending and receiving. The error log in the console of the web app is: "Origin http://localhost:3000 is not allowed by Access-Control-Allow-Origin. Fetch API cannot load http://127.0.0.1:5000/ due to access control checks. "
I ran into this issue earlier and added flask_cors and it worked for a while. Here is my server code:
from flask_cors import CORS, cross_origin
app = FlaskAPI(__name__)
app.config['SECRET_KEY'] = 'the quick brown fox jumps over the lazy dog'
app.config['CORS_HEADERS'] = 'Content-Type'
cors = CORS(app, resources={r"/": {"origins": "http://localhost:port"}})
# Also fails with this variation
# cors = CORS(app, resources={r"/api/*": {"origins": "*"}})
#app.route("/", methods=['GET', 'POST'])
#cross_origin(origin='localhost',headers=['Content- Type','Authorization'])
# Also fails with these variations
# #cross_origin(origin='http://127.0.0.1:5000/',headers=['Content- Type','Authorization'])
# #cross_origin(origin='http://localhost:3000',headers=['Content- Type','Authorization'])
def job_api():
with app.app_context():
job_data = get_job_data()
json_data = jsonify(eqtls=[job.data for job in job_data])
return json_data
if __name__ == "__main__":
app.run(debug=True)
Here is my client code:
componentDidMount() {
fetch('http://127.0.0.1:5000/')
.then(res => res.json())
.then((data) => {
this.setState({ job_data: data.eqtls })
})
.catch(console.log)
}
You need to enable CORS policy on your API, so it can accept requests from across different hosts.
Just do a google Flask cors, and make sure you are Accepting '*' or specifically your URL.
If you accept cors though you should be able to accept all CORS and then make your API robust enough so that no nasty data can be requested
Try:
from flask_cors import CORS, cross_origin
app = FlaskAPI(__name__)
app.config['SECRET_KEY'] = 'the quick brown fox jumps over the lazy dog'
app.config['CORS_HEADERS'] = 'Content-Type'
#app.route("/", methods=['GET', 'POST'])
#cross_origin()
def job_api():
with app.app_context():
job_data = get_job_data()
json_data = jsonify(eqtls=[job.data for job in job_data])
return json_data
if __name__ == "__main__":
app.run(debug=True)
I read the documenttation, and can just add #cross_origin() as a simple decorator: https://flask-cors.readthedocs.io/en/latest/#route-specific-cors-via-decorator

Flask 500/404 errors

I'm experiencing an error with Flask. If I call the #app.route with the function, I retrieve 404 Not Found:
from flask import Flask, request
import requests
app = Flask(__name__)
#app.route('/webhook', methods=['GET', 'POST'])
def webhook():
return 'Hello!'
if __name__ == '__main__':
app.run("0.0.0.0", port=10101, debug=False)
However, if the function is not mentioned, I retrieve the 500 Internal Server Error:
from flask import Flask, request
import requests
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def webhook():
return 'Hello!'
if __name__ == '__main__':
app.run("0.0.0.0", port=10101, debug=False)
Any help, please?
Your code runs fine. I just copy-pasted your original example and did a curl request to it with:
curl -X GET http://localhost:10101/webhook
curl -X POST --data "test=true" http://localhost:10101/webhook
Both return Hello!%
As suggested by #Sebastian Speitel - try enabling debug mode - that will give you an idea of what fails and why:
app.run("0.0.0.0", port=10101, debug=True)

Django test client POST command not registering through 301 redirect

I'm writing Django tests for a live Heroku server, and am having trouble getting Django to recognize a POST request through a redirect.
On my test server, things work fine:
views.py
def detect_post(request):
"""
Detect whether this is a POST or a GET request.
"""
if request.method == 'POST':
return HttpResponse(
json.dumps({"POST request": "POST request detected"}),
content_type="application/json"
)
# If this is a GET request, return an error
else:
return HttpResponse(
json.dumps({"Access denied": "You are not permitted to access this page."}),
content_type="application/json"
)
python manage.py shell
>>> from django.urls import reverse
>>> from django.test import Client
>>> c = Client()
# GET request returns an error, as expected:
>>> response = c.get(reverse('detectpost'), follow=True)
>>> response.status_code
200
>>> response.content
b'{"Access denied": "You are not permitted to access this page."}'
# POST request returns success, as expected
>>> response = c.post(reverse('detectpost'))
>>> response.status_code
200
>>> response.content
b'{"POST request": "POST request detected"}'
However, when I move over to my production server, I encounter problems. I think it's because my production server has SECURE_SSL_REDIRECT, so all pages are redirecting to an SSL-enabled version of the same page. Here's what happens when I try to run the same test code on my production server:
heroku run python manage.py shell
>>> from django.urls import reverse
>>> from django.test import Client
>>> c = Client()
# GET request returns an error, as expected:
>>> response = c.get(reverse('detectpost'), follow=True)
>>> response.status_code
200
>>> response.content
b'{"Access denied": "You are not permitted to access this page."}'
# POST request, however, has problems
>>> response = c.post(reverse('detectpost'), follow=True)
>>> response.status_code
200
>>> response.content
b'{"Access denied": "You are not permitted to access this page."}'
>>> response.redirect_chain
[('https://testserver/testpost/', 301)]
# I believe that the POST request isn't being detected because my site uses redirects
>>> response = c.post(reverse('detectpost'))
>>> response.status_code
301
How can I get my Django TestClient to register a POST request even through a redirect? I expected the follow=True flag to accomplish this, but it doesn't seem to be working.
When you use client.post, you can simulate a request to the https URL by setting secure=True.
response = c.post(reverse('detectpost'), follow=True, secure=True)
When the Django secure middleware returns a 301 redirect from http to https, browsers will make a GET request to the new URL even if the original request was a POST request.
There is a 307 response which tells the browser not to change the method. However I would not try to get Django to return a 307. Just change the client.post() call to use secure=True as I suggested above.

Python mechanize implementation of HTTP Basic Auth

I could get HTTP Basic Authentication to work using requests:
import requests
request = requests.post(url, auth=(user, pass), data={'a':'whatever'})
And also using urllib2 and urllib:
import urllib2, urllib
passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
passman.add_password(None, url, user, pass)
auth_handler = urllib2.HTTPBasicAuthHandler(passman)
opener = urllib2.build_opener(auth_handler)
urllib2.install_opener(opener)
content = urllib2.urlopen(url, urllib.urlencode({'a': 'whatever'}))
The problem is I get an unauthorized error when I try the same thing with mechanize:
import mechanize, urllib
from base64 import b64encode
browser = mechanize.Browser()
b64login = b64encode('%s:%s' % (user, pass))
browser.addheaders.append(('Authorization', 'Basic %s' % b64login ))
request = mechanize.Request(url)
response = mechanize.urlopen(request, data=urllib.urlencode({'a':'whatever}))
error:
HTTPError: HTTP Error 401: UNAUTHORIZED
The code I tried with mechanize could be trying to authenticate in a different way than the other two code snippets. So the question is how could the same authentication process be achieved in mechanize.
I am using python 2.7.12
The header should have been added to the request instead of the browser. In fact the browser variable isn't even needed.
import mechanize, urllib
from base64 import b64encode
b64login = b64encode('%s:%s' % (user, pass))
request = mechanize.Request(url)
request.add_header('Authorization', 'Basic %s' % b64login )
response = mechanize.urlopen(request, data=urllib.urlencode({'a':'whatever'}))