http GET request from python echo server using React - javascript

I have a Python echo server that sends a continuous stream of data when a client sends a GET request, as follows:
GET request for /?value=30
GET request for /?value=30
GET request for /?value=30
GET request for /?value=37
GET request for /?value=37
GET request for /?value=37
The snippet of the Python echo server, which uses the http.server library:
from http.server import BaseHTTPRequestHandler, HTTPServer
import logging
class S(BaseHTTPRequestHandler):
def _set_response(self):
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
def do_GET(self):
logging.info("GET request,\nPath: %s\nHeaders:\n%s\n", str(text), str(self.headers))
self._set_response()
self.wfile.write("get_value: GET request for {}".format(text).encode('utf-8'))
Node.js code that logged the data response above:
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
function httpGet(theUrl) {
let xmlHttpReq = new XMLHttpRequest();
xmlHttpReq.open("GET", theUrl, false);
xmlHttpReq.send(null);
return xmlHttpReq.responseText;
}
var i = 1
while (i ==1) {
console.log(httpGet('http://localhost:8080'));
}
I have successfully retrieved the data using a Node.js code however I wasn't successful in implementing it in React. How should I write a simple GET/fetch request in React? I'm very new to React and thanks for your guidance.

You can use the fetch-api to create HTTP request, here is react example:
componentDidMount() {
fetch('http://localhost:8080')
.then((res) => res.json() {
console.log(res)
})
}

Related

XMLHttpRequest sends b'' instead of json data

I'm trying to send json data from my web app to my python flask api, my server is receiving the POST rqeuest & is receiving data, the issue is that it's not receiving json data rather the string b''
This is the javascript code I got to send the json data to my api
function onSubmit() {
document.getElementById("orderbutton").disabled=true;
setTimeout('document.getElementById("orderbutton").disabled=false;',3000);
var request = new XMLHttpRequest();
var url = "http://127.0.0.1:5000/api/order";
request.open('POST', url, true)
request.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
request.onload = function() {
var response = JSON.parse(request.responseText)
console.log(response)
}
request.send(JSON.stringify({"id": document.getElementById("order").value.trim()}))
}
edit: it's not an issue with document.getElementById("order").value.trim() because when I console.log it, I get the input I put in my <input> field
Try editing your send() line to
request.send(JSON.stringify({id: document.getElementById("order").value.trim()}));
Change is from "id" to id
use .decode('utf-8'), Let me know the result.

XMLHttpRequest not being able to make a request to Flask server

I have setup a simple flask server using the following code:
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
#app.route("/")
def helloWorld():
return "Hello, cross-origin-world!"
if __name__ == '__main__':
app.run(host = '0.0.0.0', port='5000')
From js I am making a request to the address using the follwing code
const theUrl="<myip>:5000/";
var xmlHttp = new XMLHttpRequest();
xmlHttp.open( "GET", theUrl, false);
xmlHttp.send();
console.log(xmlHttp.response);
The console shows
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <title>404 Not Found</title> <h1>Not Found</h1> <p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>
When I try to access the same url from the browser, it returns
Hello, cross-origin-world!
Is there something wrong I am doing with the server? I have tried the js code on a dummy address and I am able to get the contents of that website. There is something wrong with the Flask server.
Just wrote something for file uploads.
Hope this helps.
$('.custom-file-input').change(function () {
console.log($(this)[0].files[0].name);
$('.custom-file-label').text($(this)[0].files[0].name);
var formData = new FormData();
formData.append('file', $(this)[0].files[0]);
var xhr = new XMLHttpRequest();
xhr.open('POST', '/', true);
xhr.send(formData)
I don't understand why one would use XHR for get requests, couldn't you just use Ajax instead?
The last parameter is whether the connection is asynchronous. Perhaps that's what wrong?
Also, don't use Flask built-in webserver for production environment, it just isn't made to cope with more than one user testing for example.
Furthermore, perhaps someone can tell me why not, however, I think you would be better off simply having url as the section of the url after the port declaration, in my example, notice that I only tell jquery or js to post data to / and this is because that means local server, or is interpreted to mean itself, so by default is prepended with your server IP and in this case the port 5000 aswell

Sending data with XMLHttpRequest

I have a website that should send a name to a python script (on a third-party website) when a button is pressed. This python script will then make the name uppercase and return it back to the website.
Right now an XMLHttpRequest is correctly being sent when the button is pressed, but I'm unsure how I correctly send the data with the XMLHttpRequest, and then how this data is accessed in the python script.
XMLHttpRequest:
document.getElementById("myButton").addEventListener("click",
function() {
var myRequest = new XMLHttpRequest();
myRequest.open('GET', 'https://example.com/');
myRequest.onreadystatechange = function () {
if (myRequest.readyState === 4) {
alert(myRequest.responseText);
}
}
myRequest.send("Bob"});
}
);
Python script:
from flask import Flask, jsonify
from flask_cors import CORS
from requests import request
app = Flask(__name__)
CORS(app)
#app.route("/", methods=["GET"])
def hello_world():
return jsonify(name = (name_sent_by_XMLHttpRequest).upper()) # Should return "BOB"
if __name__ == '__main__':
app.run()
I know nothing about javascripts' XMLHTTPRequest but at some point, you need to send the name to the python server, right? HOW to do that is up to you, but a GET based option:
GET request with args: https://example.com/?name=your_name_goes_here
in your flask app, the function listening on route "/" will now have access to that arg, something like
name = request.args.get('name', '')
then you can uppercase() it, and return it in some format - probably XML ?
return Response(my_xml, mimetype='text/xml')
Update based on your comment: usually in a flask function, you would use the flask request object to get your URL parameters. In your example, you're importing the requests module as request, not using it, but clobbering the flask.request namesspace. Change your imports to something like this, and it should work normally:
from flask import Flask, jsonify, request
from flask_cors import CORS
import requests

Flask Session Not Persisting (Postman works, Javascript doesn't)

I'm developing a Flask server to communicate between some backend Python functionality and Javascript clients over the web. I'm attempting to utilize Flask's session variable to store user specific data over the course of their time interacting with the app. I've removed most of the application specific code below but the core problem I'm experiencing remains.
Here is my the code for my (simplified) Flask app:
import json
import os
from flask import Flask, jsonify, request, session
app = Flask(__name__)
app.secret_key = 'my_secret_key'
#app.route('/', methods=['GET'])
def run():
session['hello'] = 'world'
return jsonify(session['hello'])
#app.route('/update', methods=['POST'])
def update():
return jsonify(session['hello'])
if __name__ == '__main__':
app.run(host='0.0.0.0')
Utilizing Postman, I can make a GET request to my server and receive the expected output of "world". I can then make a POST request with an arbitrary body and receive the same expected output of "world" (again using Postman).
When using Chrome, I can visit my server IP and see the expected output "world" on the page. I can also manually make a GET request using Javascript (in Chrome's console) and receive the same response as expected. However, my problem arises when trying to send a POST request to the server using Javascript; the server shows a KeyError: 'hello' when trying to make this request.
Here is the Javascript I'm using to make the POST request:
var url = 'http://my_server_ip/update';
fetch(url, {
method: 'POST',
body: JSON.stringify('arbitrary_string'),
headers: new Headers({
'Content-Type': 'application/json'
})
})
.then(response => response.json())
.then((data) => {
console.log(data);
})
What's going wrong here? Why can I make the GET/POST requests with Postman just fine but run into errors making the same requests with Javascript?
The caveats section of the fetch documentation says:
By default, fetch won't send or receive any cookies from the server, resulting in unauthenticated requests if the site relies on maintaining a user session.
It is recommended to use AJAX to exchange information with Flask views.
Meanwhile, in your code for the Flask app, the session object is a dictionary. Now, if you access a dictionary with its key session['hello'] and if this key does not exist, a Keyerror is raised. To get around this error, you can use the get() method for dictionaries.
What is happening is: the fetch request does not find the hello key(or GET the session value from the Flask view) in the Flask session.
user = session.get('hello')
return jsonify(session_info=user)
But this will still give you a null value for the session { session_info: null }. Why is that so?
When you send GET/POST requests to the Flask server, the session is initialized and queried from within Flask. However, when you send a Javascript fetch POST request, you must first GET the session value from Flask and then send it as a POST request to your Flask view which returns the session information.
In your code, when the POST request is triggered from fetch, when I send the payload data to Flask, it is received correctly and you check this using request.get_json() in the Flask view:
#app.route('/update', methods=['POST'])
def update():
user = session.get('hello')
payload = request.get_json()
return jsonify(session_info=user, payload=payload)
This will return { payload: 'arbitrary_string', session_info: null }. This also shows that fetch does not receive the session information because we did not call GET first to get the session information from Flask.
Remember: The Flask session lives on the Flask server. To send/receive information through Javascript you must make individual calls unless there is a provision to store session cookies.
const fetch = require('node-fetch');
var url_get = 'http://my_server_ip';
var url_post = 'http://my_server_ip/update';
fetch(url_get, {
method:'GET'
}).then((response)=>response.json()).then((data) =>fetch(url_post, {
method: 'POST',
body: JSON.stringify(data),
dataType:'json',
headers: {
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then((postdata) => {
console.log(postdata);
}));
The Flask views will change slightly:
#app.route('/', methods=['GET'])
def set_session():
session['hello'] = 'world'
return jsonify(session['hello'])
#app.route('/update', methods=['POST'])
def update():
payload = request.get_json()
return jsonify(session_info=payload)
When you trigger the Javacript request now, the output will be: { session_info: 'world' }
After a few hours of testing, I managed to figure out the issue. Although I think #amanb's answer highlights the problem, I'm going to answer my own question because what I found is ultimately a simpler solution.
In order to make the POST request return the expected value, I simply needed to add a credentials: 'same-origin' line to the fetch body. This looks like the following:
var url = 'http://my_server_ip/update';
fetch(url, {
method: 'POST',
body: JSON.stringify('arbitrary_string'),
credentials: 'same-origin', // this line has been added
headers: {
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then((data) => {
console.log(data);
})
According to Mozilla's Fetch usage guide,
By default, fetch won't send or receive any cookies from the server,
resulting in unauthenticated requests if the site relies on
maintaining a user session.
So it seems I looked over this. Changing the credentials to allow communication of the cookie/session between client and server resolved the issue.

How to retrieve a response when the request is sent by ajax (XMLHtttpRequest)

/* the following **frontend** function is invoked to
send a new post (in json) to the node server */
addPost(postData) {
const xhr = new XMLHttpRequest();
xhr.open('POST', `${process.env.REACT_APP_BACKEND}/posts`);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(postData));
}
/* the following **server** code picks up the request
from the function above */
app.post('/posts', bodyParser.json(), (request, response) => {
new Promise(resolve => {
// code to add request.body to database will be here
resolve(request.body);
})
.then(data => response.send(data)); // *** How do I retrieve
} // *** this "data" in
); // *** my frontend code?
Hi all,
The top part of my code (frontend) is an ajax that sends a request in json format.
The bottom part of my code (node/express server) does the following:
1) receives the request
2) inserts "request.body" in a database
3) sends a response back to the frontend.
This response is a Promise containing the request.body. How do I retrieve this response in my frontend code? It seems that ajax helps me send requests, but doesn't do anything about retrieving the response that comes back.
Thanks!
P.S. Since this data was originally sent from the frontend, one might say the frontend already has this data. However, I just want to know, in general, how to retrieve a response when the request is sent by ajax.
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
console.log(xhr.responseText);
}
}
xhr has an event handler onreadystatechange ,
you can say that the request has been successful when xhr.readyState == XMLHttpRequest.DONE.
more detailed doc on this can be availed # https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState
you can also get the status code of the http request from xhr.status
XMLHttpRequest is pretty Useful API, but it is too low level, it is now being superseded by FETCH API, which is awesome, it also supports promise interface, that means you can use .then and .catch , or the newer async/await.
you can read it up here # https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
and an example # https://googlechrome.github.io/samples/fetch-api/fetch-post.html

Categories

Resources