I've been trying to build this stock prediction web app using Prophet model and FastAPI. I'm stuck at this problem where I'm getting console log error: 422 Unprocessable Entity.
Here's the react code to get API request:
async function GetAPI () {
const [predData, setPred] = React.useState();
const [stock_name, setStock] = React.useState();
const axios = require('axios');
var data = JSON.stringify({
"ticker": stock_name
})
try{
let response = await axios({
method: 'post',
url:'http://0.0.0.0:8000/predict',
headers: {
'accept' : 'application/json',
'Content-Type' : 'application/json'
},
data: data
},
)
if (response.status==200){
console.log(response.data);
setPred(response.data);
}
return {predData}
}
catch(error){
console.log(error);
}
}
This is the FastAPI function in my python backend:
#app.post("/predict")
def prediction(payload: StockIn):
stock_name = payload.stock_name
pred = stock_prediction(stock_name)
a = int(pred)
response_object = {"data" : a }
return response_object
Can anyone help me out here?
First of all, you send {'ticker': '...'}.
And in backend you try to access a property called stock_name.
Most likely this is caused by it.
If that doesn't help, check below.
It seems that your situation is related with your backend, so you can edit the header.
You can check the variables by simply adding
print statements after important parts.
For example;
#app.post("/predict")
def prediction(payload: StockIn):
print('Payload:', payload)
stock_name = payload.stock_name
pred = stock_prediction(stock_name)
print('Pred:', pred)
a = int(pred)
response_object = {"data" : a }
return response_object
NOTE: It's about backend because axios doesn't interfere with the response codes.
The following code is an extract from Postman, where I am getting a response. For some reason the NodeJS version doesn't seem to be running and gives a "Socket hang up" error, where as the python version runs well. Both codes are pasted below:
const obj = {
asset: [
{
age: "33",
existingDisease: false,
gender: "MALE",
id: "883a8cb5446f4d6780db2e59bdf4ee35",
proposerRelationShip: "SELF",
used: false,
},
],
cover: [],
pinCode: "122001",
quoteId: "7637d7ff982145569fbfa604e3b74485",
sumInsured: "700000",
term: { unit: "YEAR", value: "1" },
};
const strObj = JSON.stringify(obj);
var options = {
method: "POST",
url: "https://sa.navi.com/v3/premium?paymentMode=SUBSCRIPTION",
headers: {
appversion: "2.2.4",
appversioncode: "92",
osversion: "Android_11",
deviceid: "3e44626c3bb37d4c",
defaultlocale: "en_US",
"x-session-token": "d635eb15-10aa-4315-9122-6ed3627dc1b8",
"x-click-stream-data":
'{"app":{"name":"Navi","version":"92","version_name":"2.2.4"},"device":{"device_id":"3e44626c3bb37d4c","advertising_id":"706649fa-50f0-410d-9c17-3085201808e2","manufacturer":"Google","model":"sdk_gphone_x86","os":"Android","os_version":"30"},"network":{"carrier":"Android","type":"Wifi"},"location":{"latitude":"37.4219983","longitude":"-122.084"},"user":{}}',
"x-target": "GI",
source: "APK",
"content-type": "application/json; charset=utf-8",
"content-length": "419",
"accept-encoding": "gzip",
"user-agent": "okhttp/4.9.0",
},
body: strObj,
};
console.log("Going to trigger API");
console.log(options);
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
Gives error:
Error: Error: socket hang up
While the same code in Python works:
url = "https://sa.navi.com/v3/premium?paymentMode=SUBSCRIPTION"
payload = "{\"asset\":[{\"age\":\"33\",\"existingDisease\":false,\"gender\":\"MALE\",\"id\":\"883a8cb5446f4d6780db2e59bdf4ee35\",\"proposerRelationShip\":\"SELF\",\"used\":false}],\"cover\":[],\"pinCode\":\"122001\",\"quoteId\":\"7637d7ff982145569fbfa604e3b74485\",\"sumInsured\":\"700000\",\"term\":{\"unit\":\"YEAR\",\"value\":\"1\"}}"
headers = {
'appversion': '2.2.4',
'appversioncode': '92',
'osversion': 'Android_11',
'deviceid': '3e44626c3bb37d4c',
'defaultlocale': 'en_US',
'x-session-token': 'd635eb15-10aa-4315-9122-6ed3627dc1b8',
'x-click-stream-data': '{"app":{"name":"Navi","version":"92","version_name":"2.2.4"},"device":{"device_id":"3e44626c3bb37d4c","advertising_id":"706649fa-50f0-410d-9c17-3085201808e2","manufacturer":"Google","model":"sdk_gphone_x86","os":"Android","os_version":"30"},"network":{"carrier":"Android","type":"Wifi"},"location":{"latitude":"37.4219983","longitude":"-122.084"},"user":{}}',
'x-target': 'GI',
'source': 'APK',
'content-type': 'application/json; charset=UTF-8',
'content-length': '419',
'accept-encoding': 'gzip',
'user-agent': 'okhttp/4.9.0'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
Your content-length is wrong (you're passing 419, when the actual length of your payload JSON is 279). This probably means the receiving server is still waiting for the rest of the content to arrive, it never arrives so eventually the server times out and hangs up on you (thus why you get a hang up error).
And, lo and behold, when I just remove the content-length header and let the request library compute it automatically, the request starts working for me.
As for the python implementation, one guess is that it is overriding the wrong content-length and fixing it for you.
FYI, the request() library has been deprecated and it is not recommended that people write new code with it as it will not be advanced with new features in the future. A list of suggested alternatives (that all support promises) is here. My favorite in that list is got() which also supports most of the same options as the request() library, but is promise-based at is core and has a number of API improvements that make it easier to use (in my opinion).
And, indeed your code works just fine with the got() library (after removing the incorrect content-length header).
const got = require('got');
const obj = {
asset: [{
age: "33",
existingDisease: false,
gender: "MALE",
id: "883a8cb5446f4d6780db2e59bdf4ee35",
proposerRelationShip: "SELF",
used: false,
}, ],
cover: [],
pinCode: "122001",
quoteId: "7637d7ff982145569fbfa604e3b74485",
sumInsured: "700000",
term: { unit: "YEAR", value: "1" },
};
const strObj = JSON.stringify(obj);
var options = {
method: "POST",
url: "https://sa.navi.com/v3/premium?paymentMode=SUBSCRIPTION",
headers: {
appversion: "2.2.4",
appversioncode: "92",
osversion: "Android_11",
deviceid: "3e44626c3bb37d4c",
defaultlocale: "en_US",
"x-session-token": "d635eb15-10aa-4315-9122-6ed3627dc1b8",
"x-click-stream-data": '{"app":{"name":"Navi","version":"92","version_name":"2.2.4"},"device":{"device_id":"3e44626c3bb37d4c","advertising_id":"706649fa-50f0-410d-9c17-3085201808e2","manufacturer":"Google","model":"sdk_gphone_x86","os":"Android","os_version":"30"},"network":{"carrier":"Android","type":"Wifi"},"location":{"latitude":"37.4219983","longitude":"-122.084"},"user":{}}',
"x-target": "GI",
source: "APK",
"content-type": "application/json; charset=utf-8",
"accept-encoding": "gzip",
"user-agent": "okhttp/4.9.0",
},
body: strObj,
};
console.log("Going to trigger API");
got(options).then(response => {
console.log(response.body);
}).catch(e => {
console.log(e);
});
I want the following code to be translated into GAS from python. I wrote the GAS version pasted below but it is not working. It must be something simple but I don't know the reason why I get this error. Any advice will be appreciated. Thanks.
import requests
requestId = "*******************"
url = "http://myapi/internal/ocr/"+requestid+"/ng"
payload={}
headers = {
'X-Authorization': 'abcdefghijklmn'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
I wrote this at the moment but I get bad request error.
function sending(yesorno, requestId) {
var requestId = "*******************"
var STAGING_KEY = "abcdefghijklmn"
var url = url = "http://myapi/internal/ocr/"+requestId+"/ng"
var data = {}
var options = {
'muteHttpExceptions': true,
'method': 'post',
'payload': JSON.stringify(data),
'headers': {
'X-Authorization': STAGING_KEY
}
};
//Error processing
try {
var response = JSON.parse(UrlFetchApp.fetch(url, options));
if (response && response["id"]) {
return 'sent';
} else {
//reportError("Invalid response: " + JSON.stringify(response));
//return 'error';
Logger.log('error')
}
} catch (e) {
//reportError(e.toString());
//return 'error';
Logger.log('error')
}
}
Modified Code
function sending() {
var requestId = "*************************"
var STAGING_KEY = "abcdefghijklmn"
var url = "http://myapi/internal/ocr/"+requestId+"/ng";
var data = {}
var options = {
'muteHttpExceptions': true,
'method': 'post',
'payload': data,
'headers': {
'X-Authorization': STAGING_KEY
}
};
try {
var response = JSON.parse(UrlFetchApp.fetch(url, options).getContentText());
Logger.log(response)
if (response && response["id"]) {
return 'sent';
} else {
//reportError("Invalid response: " + JSON.stringify(response));
//return 'error';
Logger.log('error1')
}
} catch (e) {
//reportError(e.toString());
//return 'error';
Logger.log('error2: '+ e.toString())
}
}
Error
error2: Exception: Bad request:
I understood your situation as follows.
Your python script works fine.
You want to convert the python script to Google Apps Script.
When your Google Apps Script is run, an error Exception: Bad request: occurs.
In this case, how about the following modification? When response = requests.request("POST", url, headers=headers, data=payload) is used with payload={}, I think that at Google Apps Script, it's 'payload': {}.
Modified script:
function sending() {
var requestId = "*******************"
var STAGING_KEY = "abcdefghijklmn"
var url = "http://myapi/internal/ocr/" + requestId + "/ng"
var data = {}
var options = {
'muteHttpExceptions': true,
'method': 'post',
'payload': data,
'headers': {
'X-Authorization': STAGING_KEY
}
};
try {
var response = JSON.parse(UrlFetchApp.fetch(url, options).getContentText());
console.log(response)
if (response && response["id"]) {
return 'sent';
} else {
//reportError("Invalid response: " + JSON.stringify(response));
//return 'error';
Logger.log('error')
}
} catch (e) {
//reportError(e.toString());
//return 'error';
Logger.log('error')
}
}
Note:
By the above modification, the request of Google Apps Script is the same as that of the python script. But if an error occurs, please check the URL and your STAGING_KEY, again. And, please check whether the API you want to use can access from the Google side.
Reference:
fetch(url, params)
I want to pass array to Python Flask but I got empty result or b'undefined=&undefined=&undefined='. Here is my code
Javascript
var test = [1, 2, 3];
$.ajax({
url: '/table',
data : test,
type: 'POST',
success: function(response) {
console.log(response);
},
error: function(error) {
console.log(error);
}
});
and Python code
app.route('/table', methods = ['POST'])
def table():
#print(request.values)
print(request.get_data())
return 'got this'
You need to use JSON to send back values that are arrays, objects, etc in javascript:
var test = [1, 2, 3];
$.ajax({
url: '/table',
data : {'payload':JSON.stringify(test)},
type: 'get',
success: function(response) {
console.log(response);
},
error: function(error) {
console.log(error);
}
});
Then, in the app:
import json
#app.route('/table')
def table():
_result = json.loads(flask.request.args.get('payload'))
return 'got this'
Use JavaScript object and send as content as application/json.
var test = {'input_1': 1, 'input_2': 2, 'input_3': 3};
$.ajax({
url: '/table',
data : JSON.stringify(test),
contentType: 'application/json',
type: 'POST',
success: function(response) {
console.log(response);
},
error: function(error) {
console.log(error);
}
});
In your flask app, you don't need import json to load received data because you have sent content as application/json.
from flask import jsonify, request
#app.route('/table', methods = ['POST'])
def table():
_result = request.json # because you have sent data as content type as application/json
return jsonify(_result) # jsonify will response data as `application/json` header.
# {'input_1': 1, 'input_2': 2, 'input_3': 3}
So I am using axios in order to send a JSON request to Django API.
axios({
method: 'post',
url: 'http://127.0.0.1:8000/' + this.state.dataRequestEndPoint,
data: (reqData)
});
Just before the axios call I can see the request:
Object {nvm: "", a: Array(1), b: Array(1), c: Array(1), d: Array(1)}
However, when it gets to Django:
class TargetClass(APIView):
def get(self, request):
Here request is empty:
(Pdb) request.data
<QueryDict: {}>
(Pdb) request.body
b''
def post(self):
pass
What am I doing wrong?
P.S. Tried to send the request with fetch as well:
fetch('http://127.0.0.1:8000/' + this.state.dataRequestEndPoint, {
method: 'POST',
body: reqData,
})
None of it works.
Here is the solution for the problem above. Apparently, axios needs to send parameters:
var reqData = this.state.requestParams
axios({
method: 'post',
url: 'http://127.0.0.1:8000/' + this.state.dataRequestEndPoint,
params: {
'a': reqData['a'],
'b': reqData['b']
}
})
.then(function (response) {
console.log(response)
})
.catch(function (error) {
console.log(error)
});
However, I don't know how good this solution is security-wise.