I'm trying to test communication between simple bottle front and backends. I'm able to get things to work on localhost on my machine, but I encounter unexpected behavior when I run the same code on a remote azure machine.
I put three files in one folder, frontend_server.py
, backend_server.py
, and index.html
. Locally, if I run the first two servers in a terminal, then navigating to localhost:4040
shows the expected output in the developer console (it prints an object {"test_backend": "test"}
). What I would like to do is run the same servers on a remote machine (12.123.123.123, say) and see the same output printed to the developer console when I navigate to http://12.123.123.123:4040
. However, in this case, I see POST http://0.0.0.0:8080/test net::ERR_CONNECTION_REFUSED
. I have also tried changing the POST URL to the remote machine's address -- in this case, the connection times out after about 10 seconds.
I suspect there is an issue with the configuration of the remote server. However, I have set inbound rules to *
for both ports 4040 and 8080.
Here is my backend. I thought there might be a CORS issue, so included the after_request hook. It doesn't seem to ever execute, however (no message is printed to the python console).
#! /usr/bin/env python3
import beaker.middleware
import bottle
import json
app = bottle.Bottle()
@app.hook("after_request")
def enable_cors():
'''From https://gist.github.com/richard-flosi/3789163
This globally enables Cross-Origin Resource Sharing (CORS) headers for every response from this server.
'''
print("after request")
bottle.response.headers['Access-Control-Allow-Origin'] = '*'
bottle.response.headers['Access-Control-Allow-Methods'] = 'PUT, GET, POST, DELETE, OPTIONS'
bottle.response.headers['Access-Control-Allow-Headers'] = 'Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token'
@app.post("/test")
def test():
print("this is just a test")
bottle.response.content_type = "application/json"
return json.dumps({"test_backend": "test"})
bottle.run(app, host="0.0.0.0", port="8080")
This is my frontend,
#! /usr/bin/env python
import sys
import os
import bottle
import argparse
@bottle.get("/")
def root_app():
return bottle.static_file("index.html", root="./")
def main():
parser = argparse.ArgumentParser(description="Frontend Server")
parser.add_argument("--host", action="store", dest="host", type=str, help="Host to bind to", default="0.0.0.0")
parser.add_argument("--port", action="store", dest="port", type=int, help="Port to listen on", default="4040")
args = parser.parse_args(sys.argv[1:])
bottle_server_kwargs = {
"host": args.host,
"port": args.port,
"server": "tornado",
"reloader": False
}
bottle.run(**bottle_server_kwargs)
return
if __name__ == '__main__':
main()
This is how I make the POST request, in an index.html
,
<!doctype html>
<html>
<head>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.js"></script>
</head>
<body>
</body>
<script type="text/javascript">
$.ajax({
type: 'POST',
crossDomain:'true',
url: "http://0.0.0.0:8080/test",
success: function(response){
console.log("success");
console.log(response);
}
});
</script>
</html>
Any ideas about what might be happening?
The issue was solved by @Joran Beasley's comment, add it as the answer to close the question :
in your ajax call url:
http://0.0.0.0:8080/test
should be url:http://64.243.2.11:8080/test
(or whatever the actual IP of the host is ...) 0.0.0.0 just means "listen on all interfaces", its not actually the IP address you are talking to.