I'm working on my first XMLHttpRequest and am not having much luck. I think the error is somewhere on the flask side because at the request.onload line, the request readystate is 1, so it skips straight to request.send().
Javascript:
// Load user's last page
loadPage('chat');
window.onpopstate = e => {
const data = e.state;
document.title = data.title;
document.querySelector('#body').innerHTML = data.text;
};
function loadPage(name) {
const request = new XMLHttpRequest();
request.open('GET', '/{name}');
request.onload = () => {
const response = request.responseText;
document.querySelector('#body').innerHTML = response;
document.title = name;
};
request.send();
};
And on the Flask side:
import requests
from flask import Flask, jsonify, render_template, request, session
#app.route('/chat', methods=['GET'])
def chat():
channel = session['channel']
print('channel: ', channel)
return jsonify ({'channel': channel, 'username': session['username']})
Also of note: After the GET request is made, 'channel' isn't printing on the server side, which tells me the GET request is just not actually being made. Any idea on what's holding me up here?
This '/{name}' is not correct string interpolation syntax. It is evaluated literally as /{name}. I would have done '/' + name, but curiosity got the better of me and found the accepted answer to this question shows the correct syntax.
Related
I am trying to communicate with the frontend to the backend. currently, I have the backend sending an expression to the frontend, and the frontend computes it. from there I want the frontend to send the computed answer back to the backend.
Forexample:
the backend sends "2+2="
the frontend computes that 2+2 = 4
the frontend then sends the answer 4 to the backend
the backend logs the answer 4
Front-end
var XMLHttpRequest = require('xhr2');
const URL = "http://localhost:5000/"
let firstNumber = Math.floor(Math.random() * 10);
let secondNumber = Math.floor(Math.random() * 10);
const express = require('express');
const app = express();
// excecuting random addition
const finalExpression = firstNumber + "+" + secondNumber + "="
console.log(finalExpression);
var xhr = new XMLHttpRequest();
xhr.open("POST", URL, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({
expression: finalExpression
}))
Back-end:
const express = require('express')
const app = express()
app.use(express.json())
app.post('/', (req, res) => {
console.log(req.body.expression);
arr = req.body.expression.split("")
console.log(parseInt(arr[0]) + parseInt(arr[2]))
// res.send(parseInt(arr[0]) + parseInt(arr[2]))
})
app.listen(5000, () => console.log())
as you can see, I tried res.send in the frontend to the backend.
You appear to have mixed things up a little.
You can't use express on the front-end - it's a node application. You shouldn't need to use XMLHttpRequest on the server at all. express will handle all the routing for you.
You should use fetch on the front-end to get/post requests to the server (I've used async/await here).
It might look a little more like this.
Server:
// Send an expression to the front-end
app.get('/getExpression', (req, res) => {
res.send(expression);
});
app.post('/postResult', (req, res) {
const result = res.body;
// Calculate whether the result is correct,
// and then send the answer back
res.send(isResultCorrect);
});
Client:
// To get the expression from the server
const response = await fetch('/getExpression');
const expression = await response.text();
// To post the result back to the server
const options = { type: 'POST', body: result };
const response = await fetch('/postResult', options);
const isResultCorrect = await response.text();
You invert frontend and backend :) It is the frontend that sends the XMLHTTPREQUEST and it is the server that processes the request and returns the response.
This being said, using res.send is the right solution to return a response. You did the right thing in BACKEND. Therefore, you can uncomment the // res.send(parseInt(arr[0]) + parseInt(arr[2])) and leave the backend code as it is.
What is missing in the FRONTEND is a code to listen to and handle this response :
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
console.log(xhr.response);
}
}
Add it after var xhr = new XMLHttpRequest();
Your code should then look like this :
var xhr = new XMLHttpRequest();
// New code added here
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
// Handle the response (ex: console.log it)
console.log(xhr.response);
}
}
xhr.open("POST", URL, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({
expression: finalExpression
}))
Having a local database running via python, I'm trying to do some api requests to it via a website. First tried both GET's and POST's as python unittest, which worked fine.
Then using javascript; GET function working perfect but my POST function, whatever I do, sends over an empty body to the python function (variable data in python code) or in other words a dict with nothing in it, while I'm passing data through it.
relevant python snippet:
conn = sq3.connect("temp.db", check_same_thread=False)
class Login(Resource):
def post(self):
data = flask.request.form.to_dict()
lst = conn.execute(f"""SELECT AccountID, Role FROM Account
WHERE Email = \"{data['email']}\"
AND PassW = \"{data['passw_hashed']}\"
""").fetchall()
return {"LoginSucces": [{"AccountId": e[0], "Role": e[1]} for e in lst]}
app = flask.Flask(__name__)
cors = CORS(app, resources={r"/*": {"origins": '*'}})
api = Api(app)
api.add_resource(Login, "/login")
app.run(port=8080)
Javascript:
function req_login(){
let email_p = document.getElementById("login_email").value
let passw = document.getElementById("login_passw").value
let data = JSON.stringify({email: email_p,passw_hashed: passw.hashCode()});
const request = new XMLHttpRequest();
request.open("POST", IP+"/login");
request.setRequestHeader("Accept", "application/json");
request.setRequestHeader('Content-Type', 'application/json');
request.send(data);
request.onload = (e) => {
let jsret = JSON.parse(request.response);
let topkey = Object.keys(jsret);
let data_arr = jsret[topkey];
alert(data_arr['AccountId']);
}
}
Tried with manual data in javascript as well to see if reading out the data was the problem, without succes with the following bit of code:
const data = `{email: "tst#gmail.com", passw: "testtest123"}`;
Where does it go wrong, what can I try/change. If you need any more info, send in comment
After quite a bit of debugging, I found the solution myself. Hope it helps someone:
replace data = flask.request.get_json()
with data = flask.request.json
I started to try react and tried to simply get the logged in user info but this does not seem to work. I have a Django view to display the user data:
def user_details_view(request, *args, **kwargs): #REST API for detailing some basic info about the user that is using the system at the moment
current_user = request.user
id = current_user.id
try:
obj = CustomUser.objects.get(id=id)
data =obj.serialize()
except:
#data['message'] = "Not Found"
status = 404
return JsonResponse(data)
I set this view in the urls and if I access it I get the data I want. However, when I try it on react I get an internal server error. Here is the code so far:
function loadUserInfo(callback){
const xhr = new XMLHttpRequest();
const method = 'GET';
const url = "http://127.0.0.1:8000/userdetails/";
const responseType = "json";
xhr.responseType = responseType; // Let the xhr request know that its getting a json
xhr.open(method, url); //This opens the request with the method and url entered
xhr.onload = function(){
console.log("This is the response: ",xhr.response)
callback(xhr.response, xhr.status)
}
xhr.onerror = function(){
callback({"message":"The request was an error"}, 400)
}
xhr.send();//Trigger that request
}
function App() {
const [info, setinfo] = useState(null)
useEffect(()=>{
const myCallBack = (response,status)=>{
console.log(response,status)
if (status === 200){
setinfo(response)
}
}
loadUserInfo(myCallBack)
},[])
I dealt with the cors and allowed hosts in the settings.py file so I no loger get those issues. What I do get on the django server log is:
UnboundLocalError: local variable 'data' referenced before assignment
I deleted the try blocks as they can be a bit redundant at the moment but I get a different error:
Restaurant_Project/venv/lib/python3.9/site-packages/django/db/models/query.py", line 435, in get
raise self.model.DoesNotExist(
accounts.models.CustomUser.DoesNotExist: CustomUser matching query does not exist.
This same error occurs if I access the view url in the Django server and I am not logged in. I would like to know what is the best way to pass the user information I want so I use it on React. What I am basically trying to do is to bring the user data from the django response to the front end or React.
The reason for the UnboundLocalError is because data is not defined if an exception occurs.
Change the lines to:
def user_details_view(request, *args, **kwargs): #REST API for detailing some basic info about the user that is using the system at the moment
current_user = request.user
id = current_user.id
data = dict()
status = 200
try:
obj = CustomUser.objects.get(id=id)
data = obj.serialize()
except:
data['message'] = "Not Found"
status = 404
return JsonResponse(data, status=status)
I am trying to create a JavaScript code that allows me to check if I can send an HTTP request to the given host, through an URL (check if the server on or not). This is my code:
<html>
<body>
<script>
function checkServer(url) {
const controller = new AbortController();
const signal = controller.signal;
const options = { mode: 'no-cors', signal };
return fetch(url, options)
.then(setTimeout(() => { controller.abort() }, 5))
.then(response => function()
{
var xhttp = new XMLHttpRequest();
xhttp.open("GET", "http://log.mywebsite.com", true);
xhttp.send();
}
)
.catch(error => function()
{
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "http://log.mywebsite.com", true);
xhttp.send();
}
)
}
checkServer('https://blahdummydamnfck.com');
</script>
</body>
</html>
But, although it can't send the HTTP request to the server, it didn't send a log request to my log server. Why is this happening with me?
the fetch does not throw. It returns an error code if the request fails, so catch is not the right way to detect a missing server. Check the response code instead
from the manual:
The fetch() method takes one mandatory argument, the path to the resource you want to fetch. It returns a Promise that resolves to the Response to that request, whether it is successful or not. You can also optionally pass in an init options object as the second argument (see Request).
So I'm doing an assignment for school and am having troubles using an API in java script. When I use XMLHttpRequest I receive the status code "0". After being frustrated from trying with XML I tried using fetch, I now get the error "Fetch failed loading: OPTIONS 'https://api-us.faceplusplus.com/facepp/v3/detect'"
To put it in context I have converted an image to base64 and need to parse that base64 as a parameter to face++ in order to do some face recognition stuff, should be cool when it works!
Here is the XML code:
function getInfo(base64) {
var request = new XMLHttpRequest();
request.open("POST", "https://api-us.faceplusplus.com/facepp/v3/detect");
request.setRequestHeader('api_key', 'my key');
request.setRequestHeader('api_secret', 'my secret');
request.setRequestHeader('image_base64', toString(base64));
request.send(null);
request.onload = function() {
console.log(request.status());
}
}
And here is the same thing attempted with fetch:
function getInfo(base64) {
var url = "https://api-us.faceplusplus.com/facepp/v3/detect"
var data = {
"api_key":"my key",
"api_secret":"my secret",
"image_base64":toString(base64)
}
var params = {
headers:{
"Content-Type":"application/json; charset=UTF-8"
},
body:data,
method:"POST"
}
fetch(url, params).then(data=>{return data.json()}).then(res=>{console.log(res.statusText)}).catch(error=>console.log(error))
}
I'm obviously missing something here and would really appreciate any help! Hope I've formatted this correctly.
you could try removing the headers params. This error
Fetch failed loading: OPTIONS
is because you are sending some header that is not recognized by the server, i would start there.