POST method keeps on sending 400 errors when being requested - python

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>

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.

Flask how to make html page show up?

Okay so I will just have some reading to do. I don't expect anyone to answer anymore. Thanks for everybody that took the effort to reply.
I have followed the following guide to create a simple python app: https://guillaumegenthial.github.io/serving.html
edit:
Okay retrospectively I should have read more stuff before asking this question. Let me try to rephrase what I am trying to do.
I am trying to access the below defined html page. There I want to input text in a textbox and then process that text in the api function defined in flask. The results I then want to output inside the html page.
I tried to find some more ressources on this, but I am new to html and flask and am struggeling.
Any tips would be appriciated.
My app.py file:
from flask import Flask, request, jsonify
from flask_cors import CORS
from serve import get_model_api
app2 = Flask(__name__)
CORS(app2) # needed for cross-domain requests, allow everything by default
model_api = get_model_api()
# default route
#app2.route('/')
def index():
return "Index API"
# HTTP Errors handlers
#app2.errorhandler(404)
def url_error(e):
return """
Wrong URL!
<pre>{}</pre>""".format(e), 404
#app2.errorhandler(500)
def server_error(e):
return """
An internal error occurred: <pre>{}</pre>
See logs for full stacktrace.
""".format(e), 500
# API route
#app2.route('/api', methods=['POST'])
def api():
input_data = request.json
output_data = model_api(input_data)
response = jsonify(output_data)
return response
if __name__ == '__main__':
app2.run(host='0.0.0.0', port=81, debug=True)
The html file:
<body>
<div class="container col-lg-6">
<div style="padding-bottom: 0.5cm">
<div class="card text-center bg-light">
<div class="card-body" style="padding-bottom: 0.2cm">
<input class="card-title form-control" type="text" id="input" name="input" placeholder="Input sentence"/>
<button class="card-text btn btn-outline-primary" id="btn">Find Entities</button>
<button class="card-text btn btn-outline-primary" id="btn2">Get random Tweet</button>
<div class="spinner" id="spinner" style="display: none">
<div class="double-bounce1"></div>
<div class="double-bounce2"></div>
</div>
</div>
<div class="card-footer bg-white">
<pre class="card-text api-pre" style="padding-bottom: 0.2cm">
<div class="item" id="api_input">Nur der HSV </div>
<div class="item" id="api_output">0 0 B-ORG</div>
</pre>
</div>
</div>
</div>
</div>
</body>
<script type="text/javascript">
function api_call(input) {
// hide button and make the spinner appear
$('#btn').toggle();
$('#spinner').toggle();
$.ajax({
url: "0.0.0.0:81/api",
method: 'POST',
contentType: 'application/json',
data: JSON.stringify(input),
success: function( data, textStatus, jQxhr ){
// toggle the spinner and button
$('#btn').toggle();
$('#spinner').toggle();
// fill the html for answer
$('#api_input').html( data.input );
$('#api_output').html( data.output );
$("#input").val("");
},
error: function( jqXhr, textStatus, errorThrown ){
$('#btn').toggle();
$('#spinner').toggle();
$('#api_input').html( "Sorry, the server is asleep..." );
$('#api_output').html( "Try again in a moment!" );
console.log( errorThrown );
},
timeout: 3000 // sets timeout to 10 seconds
});
}
$( document ).ready(function() {
// request when clicking on the button
$('#btn').click(function() {
// get the input data
var input = $("#input").val();
api_call(input);
input = "";
});
});
</script>
By adding /api you are only making a GET request and that is all that is defined:
#app2.route('/api', methods=['POST'])
def api():
input_data = request.json
output_data = model_api(input_data)
response = jsonify(output_data)
return response
If you want the information available for testing, you can just add the GET method like so:
#app2.route('/api', methods=['GET', 'POST'])
However, I think you may want to read up on HTML request methods to see what is the most appropriate type for what you are making the endpoint do.
I'm guessing the tutorial information is expecting a POST for the api, which is common. A simple example of a POST request can be done from most commandline with curl:
curl -X POST MYIP/api -d "{ \"myKey\": \"myValue\"}"
This should return whatever response that is given by the api method.

sending data, but result shows a GET request instead of POST

I am trying to use urllib to fill out a form and then retrieve the results from the submitted data.The app I'm posting to is on a server that I have to login through appgate to access. The POST form (that I see in the response in the terminal) is like this:
<form action="accuracy-upload3" method="post"
enctype="multipart/form-data">
Human: <input type="file" id="human" name="human"><br>
Machine: <input type="file" id="machine" name="machine"><br>
<input type="submit" class="submit" value="Submit" />
</form>
But even if the method is "POST" I seem to be doing a GET instead since the html from the url is all that returns, not the response from the url on the 'action' parameter. My code is as follows:
url = "https://accuracy3.html"
filename1 = 'human.txt'
filename2 = 'machine.txt'
filedata1 = open(filename1).read()
filedata2 = open(filename2).read()
values = {
"Human": filedata1,
"id": "human",
"name": "human",
"Machine": filedata2,
"id": "machine",
"name": "machine",
"value": "Submit"
}
req = urllib2.Request(url, data = urllib.urlencode(values), headers
=
{"Content-type": "application/x-www-form-urlencoded"})
response = urllib2.urlopen(req)
print response.read()
From Making a POST call instead of GET using urllib2 I see that it should be sending a POST since I've sent data, but it isn't doing that.
Can anyone see what the problem is with my script?

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.

Flask 400 bad request, bad version, bad syntax

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 :)

Categories

Resources