400 bad Request using axios, flask and react - python

I am unable to make post request via react js to python-flask server.
I am using axios. This request works on postman, but I can't seem to figure out why I can make post request from my react app.
Please see flask code:
#app.route('/match_home_types', methods=['GET', 'POST'])
def match_home_types():
area = request.form['area']
response = jsonify({
'home_types': util.match_area_with_types(area)
})
response.headers.add('Access-Control-Allow-Origin', '*')
return response
My react-redux action code:
export const matchHouseTypes = (area) => (dispatch) => {
axios
.post("http://127.0.0.1:5000/match_home_types", area)
.then((res) => {
dispatch({
type: MATCH_TYPES,
payload: res.data.home_types,
});
})
.catch((error) => {
console.log(error.response);
});
};
my react class component:
get_house_types = () => {
const { selectedOption } = this.state;
if (selectedOption == "Find a location") {
alert("Please select a valid location");
}
var area = {
area: selectedOption.replace(/(^\w|\s\w)/g, (m) => m.toUpperCase()),
};
console.log("area:", area);
this.props.matchHouseTypes(area);
};
See below error response from axios:
data: "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">↵<title>400 Bad Request</title>↵<h1>Bad Request</h1>↵<p>The browser (or proxy) sent a request that this server could not understand.</p>↵"
status: 400
statusText: "Bad Request"
Please assist

The issue was that I was not sending the API parameters the right way. Since I am sending via form data I changed my code from:
var area = {
area: selectedOption.replace(/(^\w|\s\w)/g, (m) => m.toUpperCase()),
};
to:
const formData = new FormData();
formData.append(
"area",
selectedOption.replace(/(^\w|\s\w)/g, (m) => m.toUpperCase())
);
complete function:
get_house_types = (e) => {
e.preventDefault();
const { selectedOption } = this.state;
if (selectedOption == "Find a location") {
alert("Please select a valid location");
} else {
const formData = new FormData();
formData.append(
"area",
selectedOption.replace(/(^\w|\s\w)/g, (m) => m.toUpperCase())
);
this.props.matchHouseTypes(formData);
}
};

Related

How to upload a file using expo react native?

The issue.
My code below works (uploads the file) when I run it on my phone using expo r -c
Does NOT work (no files in request object) when i run npm run web or expo r -c followed by w
import { StatusBar } from "expo-status-bar";
import { StyleSheet, Text, View, Button } from "react-native";
import * as DocumentPicker from "expo-document-picker";
export default function App() {
const _pickDocument = async () => {
let result = await DocumentPicker.getDocumentAsync({
type: "*/*",
copyToCacheDirectory: true,
});
alert(result.uri);
console.log(result);
const imageUri = result.uri.replace("file:/data", "file:///data");
const data = new FormData();
data.append("file", {
name: result.name,
type: result.mimeType,
uri: imageUri,
});
const options = {
method: "POST",
body: data,
headers: {
Accept: "application/json",
"Content-Type": "multipart/form-data",
},
};
const base_domain =
"http://192.168.1.83:5000" + "/api/v1/manager/file-upload";
fetch(base_domain, options).catch((error) => console.log(error));
};
return (
<View style={styles.container}>
<Text>Open up App.js to start working on your app!</Text>
<StatusBar style="auto" />
<Button title="Select Document" onPress={_pickDocument} />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
});
Backend
#manager.route("/file-upload", methods=["POST"])
#csrf.exempt
def upload_file():
# check if the post request has the file part
print("Request Files", request.files)
return jsonify({"status": "ok"})
For the web case request.files gives me an empty dict.

xlsx file not being exported django rest framework

I am calling ajax request from frontend to export data in excel sheet.
js
function exportData(){
create_spinner("Please wait while we export data.");
var agent = $("#agent").val()
var dateRange = $("#dateRangeValue").val()
var queue = $("#queue").val()
var direction = $("#direction").val()
var department = $("#department").val()
var serviceLevel = $("#sl").val()
$.ajax({
type: 'POST',
url: "/call-record-api/export-data/",
data: {
"agent": agent,
"dateRange": dateRange,
"queue": queue,
"direction": direction,
"department": department,
"serviceLevel": serviceLevel,
},
success: function(resultData) {
console.log("success");
hide_spinner();
},
error: function (err) {
console.log("AJAX error in request: " + JSON.stringify(err, null, 2));
create_spinner("Couldn't export data. Please try again");
setTimeout(function(){ hide_spinner()}, 1000);
}
});
}
I have gone through documentation and implemented the same.
urls.py
url(r'^call-record-api/export-data/$', ExportCallRecordView.as_view({"post":"list"})),
views.py
class ExportCallRecordView(XLSXFileMixin, ReadOnlyModelViewSet):
def get_queryset(self):
calls = export_customized_calls(self.request)
print(calls.count())
return calls
serializer_class = CallRecordSerializer
renderer_classes = [XLSXRenderer]
filename = 'call_record_export.xlsx'
But i cannot see the file getting downloaded. However i can see success in browser console and 235 as call count in server console.
You can't download files directly with ajax. You have to use tricks like this (taken from a github repo):
// jQuery ajax
$.ajax({
type: "POST",
url: url,
data: params,
success: function(response, status, xhr) {
// check for a filename
var filename = "";
var disposition = xhr.getResponseHeader('Content-Disposition');
if (disposition && disposition.indexOf('attachment') !== -1) {
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
}
var type = xhr.getResponseHeader('Content-Type');
var blob = new Blob([response], { type: type });
if (typeof window.navigator.msSaveBlob !== 'undefined') {
// IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed."
window.navigator.msSaveBlob(blob, filename);
} else {
var URL = window.URL || window.webkitURL;
var downloadUrl = URL.createObjectURL(blob);
if (filename) {
// use HTML5 a[download] attribute to specify filename
var a = document.createElement("a");
// safari doesn't support this yet
if (typeof a.download === 'undefined') {
window.location = downloadUrl;
} else {
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
}
} else {
window.location = downloadUrl;
}
setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
}
}
});
Or if you don't mind converting your POST request in to GET request:
window.location = `/<download_url>/?param1=${encodeURIComponent(param1)}`

Send file path from flask to Ajax

I'm trying to send a file path to my Ajax script which reads file contents and displays it on the page
#app.route('/main', methods=['GET'])
def main():
filename = '/static/js/'+current_user.username+'log.txt'
return render_template('main.html',name=current_user.username,data=filename)
js script
var checkInterval = 1; //seconds
var fileServer = '{{ data }}';
var lastData;
function checkFile() {
$.get(fileServer, function (data) {
if (lastData !== data) {
$( "#target" ).val( data );
$( "#target" ).animate({
scrollTop: $( "#target" )[0].scrollHeight - $( "#target" ).height()
}, 'slow');
lastData = data;
}
});
}
$(document).ready(function () {
setInterval(checkFile, 1000 * checkInterval);
});
I tried different ways to do this, changed fileServer to 'data.filename'/{{ data| json }} etc but got no luck.
How can I do this?
If you pass the entire url generated with url_for as a parameter it should work.
#app.route('/main', methods=['GET'])
def main():
filename = url_for('static', filename=f'js/{current_user.username}log.txt')
return render_template('main.html', name=current_user.username, data=filename)
As a supplement, I also specify that the request should not be stored in the cache.
const checkInterval = 1;
const fileServer = "{{ data }}";
let lastData;
function checkFile() {
$.get({ url: fileServer, cache: false }, function(data) {
if (lastData !== data) {
$("#target").val(data);
$("#target").animate({
scrollTop: $("#target")[0].scrollHeight - $("#target").height()
}, "slow");
lastData = data;
}
});
}
$(document).ready(function() {
setInterval(checkFile, 1000 * checkInterval);
});
I used jquery version 3 for testing.

amazonmq invoke aws lambda

AWS CloudWatch Events to trigger a Lambda function that polls for messages on a queue. Messages are then sent to a second Lambda function that writes the message to an Kinesis agent.
I found a solution to this article but written in node.js. But I am looking for Python script. Could you please help me to get a article where I can find a way to convert it by myself.
https://github.com/aws-samples/amazonmq-invoke-aws-lambda
const stomp = require('stompit')
const AWS = require('aws-sdk')
let lambda = new AWS.Lambda()
const QUEUE_NAME = process.env.QUEUE_NAME
const CONNECTION_OPTIONS = {
host: process.env.HOST,
port: 61614,
ssl: true,
connectHeaders: {
login: process.env.LOGIN,
passcode: process.env.PASSWORD
}
}
exports.handler = (event, context, callback) => {
var client
/* */
const onError = (error) => {
console.error(`[ERROR] ${error}`)
callback(error)
}
/* */
const onMessage = (error, message) => {
console.log('Message received')
message.readString('utf-8', (error, body) => {
if (error) {
onError(error)
return
}
let payload = {
message: body,
timestamp: Date.now()
}
console.log(payload)
let params = {
FunctionName: process.env.WORKER_FUNCTION,
Payload: JSON.stringify(payload)
}
lambda.invoke(params, (error, data) => {
if (error) {
console.error(`Could not invoke Lambda: ${error}`)
}
})
})
}
/* Main */
stomp.connect(CONNECTION_OPTIONS, (error, client) => {
if (error) {
onError(error)
return
}
var headers = {
destination: `/queue/${QUEUE_NAME}`,
ack: 'auto'
}
client.subscribe(headers, onMessage)
setTimeout(() => {
client.disconnect()
callback(null, { 'message': 'Finished' })
}, context.getRemainingTimeInMillis() - 1000)
})
}
You don't make it clear what you are trying to achieve, how far you got to, and what issue you are facing.
You can improve your question by following the the SO guidelines.
The library to interact with AWS services in python(3) is boto3.

XMLHttpRequest for sending files is not sending the data to the server

I want to upload files from a angularjs 2 app to my python server application.
the formData look perfect before sending it to the server. Containing name and file data.
On the other end is a Python API waiting to accept the file data. But i don't get the data. Debugger PDB get activated as the send is done by angularjs 2 app but i am missing the file data.
What could i be doing wrong?
upload.service.ts
import {Injectable} from 'angular2/core';
import {Http, Headers} from 'angular2/http';
#Injectable()
export class UploadService {
constructor(private http: Http) { }
uploader(files: any) {
let xhr = new XMLHttpRequest();
const formData = new FormData();
for(var i = 0; i < files.length; i++){
formData.append(files[i].name, files[i]);
}
var headers = new Headers();
headers.append('Content-Type', 'multipart/form-data');
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
resolve(JSON.parse(xhr.response))
} else {
reject(xhr.response)
}
}
}
xhr.open('POST','http://192.168.1.205:5000/zino', true)
xhr.send(formData)
}
}
python flask API debugger
As you see, the request.values are empty :(
<Request 'http://192.168.1.205:5000/zino' [POST]>
(Pdb) request.values
CombinedMultiDict([ImmutableMultiDict([]), ImmutableMultiDict([])])
This is a working example for RC angular2
import {Injectable} from '#angular/core';
import {Http, Headers, RequestOptions} from '#angular/http';
#Injectable()
export class UploadService {
constructor(private http: Http) { }
uploader(files: any) {
let xhr = new XMLHttpRequest()
const formData = new FormData()
for(var i = 0; i < files.length; i++){
formData.append(files[i].name, files[i])
}
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
//resolve(JSON.parse(xhr.response))
} else {
//reject(xhr.response)
}
}
}
xhr.open('POST','/server/upload-api', true)
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest')
xhr.send(formData)
}
}
On the python side you find the files in
(Pdb) req.httprequest.files
ImmutableDict({'IMGP0269.jpg': <FileStorage: u'IMGP0269.jpg' ('image/jpeg')>, 'IMGP0270.jpg': <FileStorage: u'IMGP0270.jpg' ('image/jpeg')>})

Categories