Flask 400 bad request, bad version, bad syntax - python

I have an issue that when i'm trying to POST a form data, flask is throwing me 400 bad request type, bad request syntax, bad request version
#app.route('/scrape', methods=['GET', 'POST'])
def scrape():
if request.method == 'POST': # ajax method
print "i reached here"
scrape_params = {
"market_name": request.form.get('market'),
"market_id": request.form.get('market-id'),
"rescrape": request.form.get('rescrape'),
"update": request.form.get('update'),
"with_investments": request.form.get('with_investments')
}
angellist.scrape(scrape_params, socketio);
return json.dumps({'success':True}), 200, {'ContentType':'application/json'}
else:
return render_template('scrape.html')
corresponding html form is
`
<form id="scrape_form" name="scrape" action="scrape" method="post" accept-charset="utf-8">
<ul>
<li>
<label for="market">Choose Market</label>
<input id="input_market" type="text" name="market" placeholder="Market" required>
<input type="hidden" id="market-id" name="market-id"/>
</li>
<li>
<span title="Rescrapes all investor information" class="checkbox-label">
<input type="checkbox" id="rescrape-checkbox" name="rescrape" value="true">Rescrape</span>
<span title="Rescrapes all companies" class="checkbox-label">
<input type="checkbox" id="update-checkbox" name="update" value="true">Update</span>
<span title="Scrapes all investments information for investors" class="checkbox-label">
<input type="checkbox" id="investments-checkbox" name="with_investments" value="true">Get Investments</span>
<li style="text-align: center;">
<input type="submit" value="Go" disabled="disabled">
</li>
</ul>
</form>
`
ajax part in js file
`
$("#scrape_form").submit(function (ev) {
var frm = $(this);
ev.preventDefault();
$.ajax({
type: 'POST',
url: "/scrape",
data: frm.serialize(),
success: function (data) {
displayLoadingScreen();
console.log("Scraping should have begun listen for socket events");
updateTimeout(socket);
},
fail: function() {
socket.disconnect();
}
});
`
the console output i'm getting is
`
127.0.0.1 - - [09/Jun/2017 00:52:37] code 400, message Bad HTTP/0.9 request type ('\x16\x03\x01\x00\xae\x01\x00\x00\xaa\x03\x03;/\x01\xc2\x95')
127.0.0.1 - - [09/Jun/2017 00:52:37] " « ¬;/┬ò╠8R⌐╙ô|┬£á∩üR'▀s╝èΘ┬ô{ ::└+└/└,└0╠⌐╠¿└└ £ ¥ / 5 " 400 -
(14904) accepted ('127.0.0.1', 62524)
127.0.0.1 - - [09/Jun/2017 00:52:38] code 400, message Bad request syntax ('\x16\x03\x01\x00\xae\x01\x00\x00\xaa\x03\x03g\xb0\xc3\xce\x14\xbb\x12\xa4\xbd\x8c8\xe2\xb0eP\x1bs6\xb4m\x16\xda=\xb6(\x95\xb0e;\xf3_\xe2\x00\x00\x1cjj\xc0+\xc0/\xc0,\xc00\xcc\xa9\xcc\xa8\xc0\x13\xc0\x14\x00\x9c\x00\x9d\x00/\x005\x00')
127.0.0.1 - - [09/Jun/2017 00:52:38] " « ¬g░├╬╗ñ╜î8Γ░eP6┤m┌=╢(ò░e;≤_Γ jj└+└/└,└0╠⌐╠¿└└ £ ¥ / 5 " 400 -
(14904) accepted ('127.0.0.1', 62526)
127.0.0.1 - - [09/Jun/2017 00:52:40] code 400, message Bad HTTP/0.9 request type ('\x16\x03\x01\x00\xae\x01\x00\x00\xaa\x03\x03\xdfL\xb4\xf5t$\xadM\x1f*\xa3\xf2\xe2\x8b,\xbf"\x1a.\x85>\xcf\xc5q')
127.0.0.1 - - [09/Jun/2017 00:52:40] " « ¬▀L┤⌡t$¡M*ú≥Γï,┐".à>╧┼qj├UQ╧üO ┌┌└+└/└,└0╠⌐╠¿└└ £ ¥ / 5 " 400 -
(14904) accepted ('127.0.0.1', 62527)
127.0.0.1 - - [09/Jun/2017 00:52:45] code 400, message Bad request version ('\xaf)\xd6\xc9\x8a\xbd\x0e\xc2vI\x05\x86\x12\xc1\x0f>\x00\x00\x1czz\xc0+\xc0/\xc0,\xc00\xcc\xa9\xcc\xa8\xc0\x13\xc0\x14\x00\x9c\x00\x9d\x00/\x005\x00')
127.0.0.1 - - [09/Jun/2017 00:52:45] " « ¬}T|⌠╔ëaá{jàç┘┘»)╓╔è╜┬vIå┴> zz└+└/└,└0╠⌐╠¿└└ £ ¥ / 5 " 400 -
`

Have you tried using https? So instead of loading http://127.0.0.1:5000/scrape, load https://127.0.0.1:5000/scrape in your browser (depending on your port). I had a similar error-output and this work for me :)

Related

access to XMLHttpRequest at 'http://127.0.0.1:5000/product' from origin 'http://localhost:3000'

I'm trying to make a POST request from my frontend(react) to my backend(python, flask and MySql) but I'm getting this error message.
Access to XMLHttpRequest at 'http://127.0.0.1:5000/product' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Network Tab Error Message
I am getting this on the server terminal, it's not showing me the POST method.
I'm not getting this error message while making a GET request, it's only happening in the POST request but POST is working fine if I make it from POSTMAN.
frontend form code
import React, { useState } from "react";
import { useDispatch } from "react-redux";
import { createProduct } from "../../actions/products";
import Button from "./Button";
import Input from "./Input";
import Label from "./Label";
const Modal = ({ showModal, setShowModal }) => {
const dispatch = useDispatch();
const [name, setName] = useState("");
const [unit, setUnit] = useState();
const [pricePerUnit, setPricePerUnit] = useState();
const handleSubmit = async (e) => {
e.preventDefault();
const product = {
product_name: name,
uom_id: parseInt(unit),
price_per_unit: parseInt(pricePerUnit),
};
console.log(product);
await dispatch(createProduct(product));
};
return (
<form onSubmit={handleSubmit}>
<div>
<Label children="Name" />
<Input
children="Name"
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
</div>
<div>
<Label children="Unit" />
<Input
children="Unit"
type="number"
value={unit}
onChange={(e) => setUnit(e.target.value)}
/>
</div>
<div>
<Label children="Price Per Unit" />
<Input
children="Price Per Unit"
type="number"
value={pricePerUnit}
onChange={(e) => setPricePerUnit(e.target.value)}
/>
</div>
<div className="flex items-center justify-end py-6 border-t border-solid border-blueGray-200 rounded-b">
<button
className="text-red-500 background-transparent font-bold uppercase px-6 py-2 text-sm outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150"
type="button"
onClick={() => setShowModal(false)}
>
Close
</button>
<Button type="submit">Save</Button>
</div>
</form>
);
};
export default Modal;
createProduct action
import * as api from "../api";
export const createProduct = (product) => async (dispatch) => {
try {
const { data } = await api.createProduct(product);
dispatch({ type: "CREATE", payload: data });
// toast.success("Product submitted");
} catch (error) {
console.log(error);
// toast.error(error.message);
}
};
../api API code
import axios from "axios";
const API = axios.create({ baseURL: process.env.REACT_APP_BASE_URL });
export const createProduct = (newProduct) =>
API.post("/product", newProduct);
backend code:
#app.route('/product', methods=['POST'])
def insert_product():
request_payload = request.json
print(request_payload)
product_id = products_dao.insert_new_product(connection, request_payload)
response = jsonify({
'product_id': product_id
})
response.headers.add('Access-Control-Allow-Origin', '*')
return response
Postman request screenshot
Preflight request screenshot
CORS issues are due to a cross-origin request. Ensure that the server has the CORS settings set up and is returning the Access-Control-Allow-Origin: * header. The preflight will check to see if the cross-site request is allowed, and then the real request will take place.

POST method keeps on sending 400 errors when being requested

I have been currently working with Flask & MongoDB for experimenting around with a small application. I'm currently having the user get all of the laws in a MongoDB collection and create a new law via a POST method to the MongoDB collection by sending JSON to the server.
However, the output below shows that sending a POST request to /post/law will send out a 400 error.
127.0.0.1 - - [12/Aug/2020 09:21:50] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [12/Aug/2020 09:21:50] "GET /laws HTTP/1.1" 200 -
127.0.0.1 - - [12/Aug/2020 09:21:54] "POST /post/law HTTP/1.1" 400 -
I've been a bit confused about why this error is happening. I know that 400 errors are usually connected to bad requests, however, I'm not sure where the bad request error is happening?
# This handles the POST request
#app.route('/post/law', methods = ["POST"])
def post_law():
if request.is_json:
content = request.get_json()
print(content)
Client-side:
<!--This tries to send a request to /post/law-->
<h1>Submit a Law</h1>
<form action="", method="GET">
<div id="law_name_section">
<label>Name of the law:</label>
<input type="text" required id="law_name">
</div>
<div id="law_description_section">
<label>Description of the law:</label>
<input type="text" required id="law_description">
</div>
<div id="law_url_section">
<label>URL to the law:</label>
<input type="text" required id="law_url">
</div>
<input type="submit" value="Submit law" onclick="submitLaw()">
</form>
<script>
// submitLaw() tries to send a request to /post/law in a JSON request
async function submitLaw() {
let name = await document.getElementById('law_name').value
let description = await document.getElementById('law_description').value
let url = await document.getElementById('law_url').value
let options = {
method: "POST",
headers: { "Content-Type": "application/json" },
body: {
name: name,
description: description,
url: url,
status: "Bill"
}
}
let response = await fetch("http://127.0.01:8000/post/law", options)
if (response.ok) {
alert("Successfully sent data to /post/law")
} else {
alert(`Couldn't send data to /post/law`)
}
}
</script>
Could be because your view does not return a response. Try:
#app.route('/post/law', methods = ["POST"])
def post_law():
if request.is_json:
content = request.get_json()
print(content)
return "hello"
Also, your URL is malformed. Should be:
await fetch("http://127.0.0.1:8000/post/law", options)
And, why all the async calls? The only thing that should be async is your fetch()
You also have 2 submits occurring. Try this:
<!--This tries to send a request to /post/law-->
<h1>Submit a Law</h1>
<form action="", method="POST">
<div id="law_name_section">
<label>Name of the law:</label>
<input type="text" required id="law_name">
</div>
<div id="law_description_section">
<label>Description of the law:</label>
<input type="text" required id="law_description">
</div>
<div id="law_url_section">
<label>URL to the law:</label>
<input type="text" required id="law_url">
</div>
<input type="button" value="Submit law" onclick="submitLaw();">
</form>
<script>
// submitLaw() tries to send a request to /post/law in a JSON request
function submitLaw() {
let name = document.getElementById('law_name').value;
let description = document.getElementById('law_description').value;
let url = document.getElementById('law_url').value;
let options = {
method: "POST",
headers: { "Content-Type": "application/json" },
body: {
name: name,
description: description,
url: url,
status: "Bill"
}
}
let response = await fetch("http://127.0.0.1:8000/post/law", options)
if (response.ok) {
alert("Successfully sent data to /post/law")
} else {
alert(`Couldn't send data to /post/law`)
}
}
</script>

Filename breaks when passed from Flask to Jinja2 [duplicate]

This question already has an answer here:
Reference template variable within Jinja expression
(1 answer)
Closed 2 years ago.
When I'm sending a filename as a variable from flask to jinja2 it breaks:
I'm using SQLAlchemy to store datas about projects (title, description and a picture to illustrate), and flask to send this data to a jinja2 page. This is the route:
#app.route('/projects')
def projects():
project_matrix = listOfProjects()
for i in range(0, len(project_matrix)):
print(project_matrix[i][3])
return render_template("projects.html", projects=project_matrix)
print(project_matrix[i][3]) shows in the terminal the name of the file of the picture for each project. This is what appears in the terminal when I reload the page
tethermc.jpg
graph.png
127.0.0.1 - - [13/May/2020 01:07:20] "GET /projects HTTP/1.1" 200 -
127.0.0.1 - - [13/May/2020 01:07:20] "GET /static/css/main.css HTTP/1.1" 200 -
127.0.0.1 - - [13/May/2020 01:07:20] "GET /static/img/uploads/%7B%7Bproject%5B3%5D%7D%7D HTTP/1.1" 200 -
127.0.0.1 - - [13/May/2020 01:07:20] "GET /favicon.ico HTTP/1.1" 200 -
and this is the template of the page:
{% for project in projects %}
<div class="project">
<div class="projectTitle">
{{ project[1] }}
</div>
<div class="projectHolding">
<div class="projectDescription" type="html">
{{ project[2] }}
</div>
<div class="projectImg">
<img
src="{{ url_for('static', filename = 'img/uploads/'+'{{project[3]}}') }}"
style="min-width: 100px; max-height: 300px;"
alt="alt"
/>
</div>
</div>
</div>
{% endfor %}
When I load the page, the content isn't altered except the images that don't show up. When I inspect the elements (the image block) I see:
<img
src="/static/img/uploads/%7B%7Bproject%5B3%5D%7D%7D"
style="min-width: 100px; max-height: 300px;"
alt="alt"
/>
There is src="/static/img/uploads/%7B%7Bproject%5B3%5D%7D%7D"
instead of src="/static/img/uploads/ethermc.jpg"
or src="/static/img/uploads/graph.png"
Do you have any idea of what's causing the problem ?
The problem is on this line:
src="{{ url_for('static', filename = 'img/uploads/'+'{{project[3]}}') }}".
First, there are single quotes around this part: '{{project[3]}}' which is causing those characters to be interpreted literally, rather than doing "what you wanted" and using the value in the project[3] variable. If you URL encode a curly brace, you get %7B or %7D, which might help you see how your incorrect filename was composed!
Second, you are "nesting" your curly braces, which isn't needed. The {{ }} next to project[3] are being interpreted literally as braces, which are being encoded to the %7B and %7D you are seeing in your final filenames. They are not needed here, because when you opened the "outside" curly braces, you are now in a code block, and everything in between is (basically) python code.
So the Python code you want to run is:
url_for('static', filename = 'img/uploads/'+project[3])
This means you should replace that line with:
src="{{ url_for('static', filename = 'img/uploads/'+project[3]) }}"

ajax request give 400 error with flask due bad json

Ok!! I'm building a flask web app, and I want to use Ajax to send some json data
Here is my code!! for the HTML and js :
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>Check your Grades</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="{{ url_for('static', filename='js/bootstrap3-typeahead.min.js')}}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/index.js')}}"></script>
<link rel="stylesheet" href="{{url_for('static', filename='css/style.css')}}">
</head>
<body>
<link href='https://fonts.googleapis.com/css?family=Lato' rel='stylesheet' type='text/css'>
<form id="predict-form" method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<p> welcome to grade predictor app,</p>
<p>Dear Plateform,</p>
<p>je viens
<label for="SCHOOL_RIGHT"> de </label>
<input class="typeahead" type="text" name="SCHOOL_RIGHT" id="SCHOOL_RIGHT" minlength="3" placeholder="(votre ecole de provenance)" data-provide="typeahead" autocomplete="off" required> et </p>
<p>dans
<label for="OPTION_RIGHT">l'option</label>
<input class="typeahead"
name="OPTION_RIGHT" id="OPTION_RIGHT" data-provide="typeahead" placeholder="(choisissez votre option )" required>
</p>
<p>j'ai obtenu
<label for="DIPPERC"></label>
<input type="number" name="DIPPERC" min="50" max="100" id="DIPPERC" placeholder="(Poucentage du
diplome )" required> % à l\'exetat
</p>
<p>
<button type="submit">
<svg version="1.1" class="send-icn" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="100px" height="36px" viewBox="0 0 100 36" enable-background="new 0 0 100 36" xml:space="preserve">
<path d="M100,0L100,0 M23.8,7.1L100,0L40.9,36l-4.7-7.5L22,34.8l-4-11L0,30.5L16.4,8.7l5.4,15L23,7L23.8,7.1z M16.8,20.4l-1.5-4.3
l-5.1,6.7L16.8,20.4z M34.4,25.4l-8.1-13.1L25,29.6L34.4,25.4z M35.2,13.2l8.1,13.1L70,9.9L35.2,13.2z" />
</svg>
<small>send</small>
</button>
</p>
</form>
<script >
var csrf_token = "{{ csrf_token() }}";
// this will send a token each time before a session started
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrf_token);
}
}
});
//submit form data
$("form#predict-form").submit(function(e){
console.log("form submitted")
e.preventDefault();
var data = {
}
var Form = this;
//Gathering the Data
//and removing undefined keys(buttons)
$.each(this.elements, function(i, v){
var input = $(v);
data[input.attr("name")] = input.val();
delete data["csrf_token"];
delete data["undefined"];
});
data["DIPPERC"] = data["DIPPERC"]/100.0
//Form Validation goes here....
//Save Form Data........
$.ajax({
cache: false,
url : "{{url_for('predict')}}",
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
data : JSON.stringify(data),
success : function(callback){
//Where $(this) => context == FORM
console.log("data sucessfuly submitted")
console.log(JSON.parse(callback));
}
,
error : function(){
console.log('erroor')
}
});
})
</script>
</body>
</html>
I've tried everything possible but still getting the 400 error!
I've checked all related questions but nothing.
But my research shows that the 400 error can be caused by this according to :
from here it's said that :
The HTTP 400 Bad Request response status code indicates that the server could not understand the request due to invalid syntax. The client should not repeat this request without modification.
Csrf token missing this I've already added the token , and try to send the data to the route with csrf.exempt but nothing
ContentType and applicationType not set (already do it but nothing)
Already check in the official flask documentation they say : (from )
I'm sending correct json data
So what may cause this problem ???
here is my simple view function
#predictions.route('/predictions/predict/', methods=['GET', 'POST'])
def predict():
if request.method == 'POST':
print "hello----------------------"
print request.method
print request.get_json(force=True)
return "done "
Note in my test when I send directly data via python to my route it works with this code :
def test_1_can_connect_post(self):
"""
Test API can create a (POST request)
"""
new_student = {
'DIPPERC':0.60, 'SCHOOL_RIGHT':'itfm/bukavu', 'OPTION_RIGHT':'elec indust'
}
res = self.client().post('predictions/predict/', data=json.dumps(new_student), content_type='application/json')
self.assertEqual(res.status_code, 201)
Ps: I'm sure that I'm missing a little thing but don't know what, maybe something wrong with ajax asynchronous .....
You don't need to convert your data into string: remove the JSON.stringify:
$.ajax({
cache: false,
url : "{{url_for('predict')}}",
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
data : data,
success : function(callback){
//Where $(this) => context == FORM
console.log("data sucessfuly submitted")
console.log(JSON.parse(callback));
},
error : function(){
console.log('erroor')
}
});
With JSON.stringify you convert your data into a string, so you post a string, no JSON.
Ok , after 7 days of debugging i just found a solution for my problem :
i do two things:
from now and for my future web development i will stop using jquery and I'm sure that soon i will found good reason for that ,
so for my code i decide to use plain javascript and here is the code i use to send the request :
var csrf_token = "{{ csrf_token() }}";
// this will send a token each time before a session started
var form = document.getElementById("predict-form");
form.onsubmit = function (e) {
// stop the regular form submission
e.preventDefault();
// collect the form data while iterating over the inputs
var formEntries = new FormData(form).entries();
var data = Object.assign(...Array.from(formEntries, ([x,y]) => ({[x]:y})));
delete data["csrf_token"];
data["DIPPERC"] = data["DIPPERC"]/100.0
console.log(data);
// construct an HTTP request
var xhr = new XMLHttpRequest();
xhr.open(form.method, form.action, true);
xhr.setRequestHeader("X-CSRFToken", csrf_token);
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
// send the collected data as JSON
xhr.send(JSON.stringify(data));
xhr.onloadend = function () {
console.log('blallala ')
};
};
this was for the javascript part and I was sure that i was sending good json object to my server
i went here at flask official documentation and found these 2 lines of attributes of flask request object
is_json :
Indicates if this request is JSON or not. By default a request is considered to include JSON data if the mimetype is application/json or application/*+json.
and
data
Contains the incoming request data as string in case it came with a mimetype Flask does not handle
and change my backend code to this :
#predictions.route('/predictions/predict/', methods=['GET', 'POST'])
def predict():
"""
the main methode use to predict
"""
if request.method == 'POST':
print "hello----------------------"
print request.is_json
print request.data
print '-----------------------------------------'
return "done "
And VOILA!!!! get the 200 status code and the data as a python dict.

python get form data how can this be?

This is my js function for ajax form submit:
$('.sendButton').on('click', function(){
$.post( "/send-form", $('#contactForm').serialize())
}
This is my form:
<form id="contactForm">
<input id="fastName" name="name" type="text" />
<input id="fastPhone" name="phone" type="text" />
<div class="sendButton">send</div>
</form>
And this is my backend function to handle it, I am using python, flask
#app.route("/send-form", methods=['POST'])
def send_form():
data = request.data
print request.data
And in my console it prints data:
127.0.0.1 - - [22/Feb/2015 23:50:54] "POST /send-form HTTP/1.1" 200 - name=dfdsf&phone=89920203725
But I did the same in another project and it prints nothing.
Details are here:
Can't get post ajax request data python
How can this be possible?
The data is in the field request.form, and can be fetched by:
name = request.form['name']
phone = request.form['phone']
Remark. If they are not sent with, this code will throw an exception.
Longer explanation
The reason is that the data is sent using a encoding known as application/x-www-form-urlencoded. The data is in request.data field, but to decode it you can use request.form, and Flask will automatically decode it as application/x-www-form-urlencoded.

Categories

Resources