I'm using python to host a simple LAN web page using HTTPRequestHandler:
from http import server # Our http server handler for http requests
import socketserver # Establish the TCP Socket connections
import json
PORT = 9000
messages = []
headers = []
class HTTPRequestHandler(server.BaseHTTPRequestHandler):
def do_HEAD(self):
self.send_response(200)
def do_GET(self):
self.send_response(200)
if self.path != '/':
return None
self.send_header("Content-Type", "text/html")
self.send_header("Connection", "Stop")
self.end_headers()
response_html = """
<html>
<head>
<title>
Testa
</title>
</head>
<body id="body">
<h1 style="color:blue">
Test
</h1>
<p>
<input type="text" id="message" placeholder="Your message">
<button onclick="sendMessage()">Send Message</button>
<p class="result" style="color:blue">
</p>
<script language="javascript" type="text/javascript">
function sendMessage(){
let messagebox = document.querySelector('#message');
// Creating an XHR object
let xhr = new XMLHttpRequest();
let url = "/message";
// open a connection
xhr.open("POST", url, true);
// Set the request header i.e. which type of content you are sending
xhr.setRequestHeader("Content-Type", "application/json");
// Converting JSON data to string
var data = JSON.stringify({ "message": messagebox.value});
// Sending data with the request
xhr.send(data);
// Clearing the messagebox
messagebox.value = ""
}
</script>
</html>
"""
self.wfile.write(response_html.encode("utf-8"))
return
def do_POST(self):
self.send_response(200)
length = int(self.headers['content-length'])
message = json.loads(self.rfile.read(length).decode("utf-8"))
print(message)
messages.append(message)
headers.append([self.headers, self.command])
Handler = HTTPRequestHandler
with socketserver.TCPServer(("", PORT), Handler) as httpd:
print("HTTP server started at:", PORT)
httpd.serve_forever()
In essence, it creates this page:
And adds a function to the button, so that a POST request is sent to the server containing whatever was in the box. This part works fine.
My issue is that every time this POST request is sent, it is paired with another identical one:
HTTP server started at: 9000
127.0.0.1 - - [14/Sep/2022 17:23:18] "POST /message HTTP/1.1" 200 -
{'message': 'Hello World!!'}
127.0.0.1 - - [14/Sep/2022 17:23:39] "POST /message HTTP/1.1" 200 -
{'message': 'Goodbye World!!'}
127.0.0.1 - - [14/Sep/2022 17:23:39] "POST /message HTTP/1.1" 200 -
{'message': 'Goodbye World!!'}
127.0.0.1 - - [14/Sep/2022 17:23:52] "POST /message HTTP/1.1" 200 -
{'message': 'In-the-middle World!!'}
127.0.0.1 - - [14/Sep/2022 17:23:52] "POST /message HTTP/1.1" 200 -
{'message': 'In-the-middle World!!'}
127.0.0.1 - - [14/Sep/2022 17:24:05] "POST /message HTTP/1.1" 200 -
{'message': 'Possibly World!!'}
127.0.0.1 - - [14/Sep/2022 17:24:05] "POST /message HTTP/1.1" 200 -
{'message': 'Possibly World!!'}
With the occasional solo POST on the first send.
I've looked into it, and this is usually because
- Something redirects, or errs, causing the code to be restarted, and activated twice. While I am completely new to HTTP, JS, PHP, etc. (the web languages), I cannot see that happening here
- A
PreFlight
operation happens, where the server sends a preliminary request to see if the main request can be sent (question). I looked into that, and I do not think that is the case, as the headers are identical in both requests:
>>> pprint.pprint(dict(h1))
{'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'en-US,en;q=0.9',
'Connection': 'keep-alive',
'Content-Length': '18',
'Content-Type': 'application/json',
'Host': 'localhost:9000',
'Origin': 'http://localhost:9000',
'Referer': 'http://localhost:9000/',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '
'(KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36 '
'Edg/105.0.1343.33',
'sec-ch-ua': '"Microsoft Edge";v="105", " Not;A Brand";v="99", '
'"Chromium";v="105"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'sec-gpc': '1'}
>>> pprint.pprint(dict(h2))
{'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'en-US,en;q=0.9',
'Connection': 'keep-alive',
'Content-Length': '18',
'Content-Type': 'application/json',
'Host': 'localhost:9000',
'Origin': 'http://localhost:9000',
'Referer': 'http://localhost:9000/',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '
'(KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36 '
'Edg/105.0.1343.33',
'sec-ch-ua': '"Microsoft Edge";v="105", " Not;A Brand";v="99", '
'"Chromium";v="105"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'sec-gpc': '1'}
And both contain the main message content
- The JavaScript is somehow being loaded twice, causing two functions to run simultaneously (question). As the JavaScript function I've written clears the input box immediately after sending it, and there is always some lag or latency, I doubt this is the case, but I don't know enough to disprove it
Regardless, I am now stuck. Everything I seem to try has no effect on cancelling this unpredictable (Sometimes the first message doesn't fire, sometimes it does) double POST, and cancelling it is mildly important to the messaging application I'm trying to shape this into. On top of using double the processing power, it is just incredibly inconvenient. Is there a way to stop this?