sending a python request to a different host on the same network - python

Currently I have something called a client, and a server.py that is running a flask server. I also have a different machine running a different flask server. (With the host being the ip address of the machine)
on one of the app routes, it will reroute the request to the different machine (Because of reasons) to process
Essentially, it looks something like this
server.py
#app.route('/endpointapi', methods = ['POST'])
def doStuff():
f = request.form['message']
correctURL = "http://somenumber.2.3:port/endpointapi"
r = requests.post(correctURL, data={'message', f})
return r
differentMachineOneSameNetwork.py
#app.route('/endpointapi', methods = ['POST'])
def doStuff():
//does things correctly
return updated message
The somenumber.2.3 is a valid ip address of the machine that is running differentMachineOneSameNetwork.py along with the port. Both machines are running a flask webserver, but the client can only send requests to the server.py. However, it is not connecting. Is there any reason why it might not be working?
EDIT
The ports are artifically chosen. 5555 for the server.py, and 8090 for the different machine. It works when we just test connections from the same machine to its own using curl commands, but it does not work when we try to curl from server machine to the other machine.
Whats working:
Curl from server to server flask
Curl from differentMachine to differentMachine flask
Curl from differentMachine to server flask
Not working:
Curl from server to differentMachine doesn't work. Connection just times out. Example command that was sent:
curl -X POST -F "message=some bojangle" http://correct.ip.address:8090/endpointapi
I get:
curl: (7) Failed to connect to correct.ip.address port 8090: Connection timed out
It just times out after trying to establish a connection, giving http response code of 500.

Related

How can i have connection to 0.0.0.0 port 5000?

I'm Creating an endpoint that retrieves the number of each objects by type. when i execute the code with:
curl -X GET http://0.0.0.0:5000/api/v1/stats
it says:
curl: (7) Failed to connect to 0.0.0.0 port 5000: Connection refused
i've been trying to see if I have a config file, checked my listed ports, Google on how to change/activate the port, & still haven't found something.
This is my full code:
''' module that makes this an app '''
from flask import Flask, abort, jsonify
from models import storage
from api.v1.views import app_views
from os import getenv
app = Flask(__name__)
app.register_blueprint(app_views)
#app.teardown_appcontext
def close(self):
''' method that close the yes '''
storage.close()
#app.errorhandler(404)
def invalid_route(e):
return jsonify({"error": "Not found"}), 404
if __name__ == '__main__':
app.run(host=getenv("HBNB_API_HOST", "0.0.0.0"),
port=int(getenv("HBNB_API_PORT", "5000")), threaded=True)```
Your code is completely right, you are not sending the request to the right host.
Your flask server is binded to 0.0.0.0, which means that your server will be bounded to the default address (either localhost or your actual ip address)
This should be fine:
curl -X GET http://localhost:5000/api/v1/stats
I used an executable command like this:
HBNB_MYSQL_USER=hbnb_dev HBNB_MYSQL_PWD=hbnb_dev_pwd HBNB_MYSQL_HOST=localhost HBNB_MYSQL_DB=hbnb_dev_db HBNB_TYPE_STORAGE=db HBNB_API_HOST=0.0.0.0 HBNB_API_PORT=5000 sudo python3 -m api.v1.app
but I forgot to add sudo before python3. Then you should open a new terminal and execute the curl command. THANKS

Cannot hit grpc server after successfully deploying to cloud run

Similar situation to what was asked here, however the solution described there do not work in my case. I want to run a grpc server on google cloud run, and be able to call it. I have a basic python grpc server that works fine and is able to be called by my client when running the gcr.io image on localhost with docker run. However, after successfully deploying to google cloud run, and with the server listening on port 8080 (I logged it), I am no longer able to reach the server with my client code.
I receive the following:
grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
status = StatusCode.UNAVAILABLE
details = "DNS resolution failed"
debug_error_string = "{"created":"#1591245267.073965000","description":"Failed to pick subchannel","file":"src/core/ext/filters/client_channel/client_channel.cc","file_line":3981,"referenced_errors":[{"created":"#1591245267.073946000","description":"Resolver transient failure","file":"src/core/ext/filters/client_channel/resolving_lb_policy.cc","file_line":214,"referenced_errors":[{"created":"#1591245267.073945000","description":"DNS resolution failed","file":"src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc","file_line":357,"grpc_status":14,"referenced_errors":[{"created":"#1591245267.073882000","description":"C-ares status is not ARES_SUCCESS: Domain name not found","file":"src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc","file_line":244,"referenced_errors":[{"created":"#1591245267.059636000","description":"C-ares status is not ARES_SUCCESS: Domain name not found","file":"src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc","file_line":244}]}]}]}]}"
>
my server code is as follows:
def serve():
# expected port from google cloud run is 8080
port = os.getenv('PORT')
if not port:
port = server_port
server.add_insecure_port('[::]:{port}'.format(port=port))
server.start()
logger.info('listening on port {port}'.format(port=port))
server.wait_for_termination()
my client code, I have tried both
channel = grpc.insecure_channel('<the .run.app url on my cloud run service>:8080')
stub = my_service_pb2_grpc.MyServiceStub(channel)
request = my_service_pb2.MyEndpointRequest(
test='hello'
)
response = stub.MyEndpoint(request)
print(response)
and
with grpc.secure_channel('<the .run.app url on my cloud run service>:8080', grpc.ssl_channel_credentials()) as channel:
stub = my_service_pb2_grpc.MyServiceStub(channel)
request = my_service_pb2.MyEndpointRequest(
test='hello'
)
response = stub.MyEndpoint(request)
print(response)
both of which do not work and gives me the same error that I wrote above.
Furthermore, when I ping <the .run.app url on my cloud run service> on the command line I get Name or service not known.
Any help would be greatly appreciated!
Managed to solve it, the solution was to remove the https:// prefix from the url shown on the cloud run service and use the 443 port instead of 8080
with grpc.secure_channel(
'<url without https:// prefix>:443',
grpc.ssl_channel_credentials(),
) as channel:
stub = my_service_pb2_grpc.MyServiceStub(channel)
request = my_service_pb2.MyEndpointRequest(
test='hello'
)
response = stub.MyEndpoint(request)
print(response)

Why is python-requests to localhost slow?

I have a simple flask server defined like so:
import sys
import flask
from flask import request
app = flask.Flask(__name__)
port = 4057
#app.route('/search', methods=['POST'])
def search():
request.json['query']
results = ['fake', 'data']
return flask.jsonify(results)
if __name__ == '__main__':
app.config['TEMPLATES_AUTO_RELOAD'] = True
app.run(host='0.0.0.0', port=port, debug=(port != 80))
I have a simple client defined like this:
import json
import requests
headers = {'content-type': 'application/json'}
resp = requests.post('http://localhost:4057/search', json.dumps({'query': 'foo'}), headers=headers)
print resp.content
The client works, but it takes like 3 seconds to complete the request.
curl completes in like half a second:
curl 'http://localhost:4057/search' -H 'Content-Type: application/json' -d '{"query": "foo"}'
Try 127.0.0.1 There maybe some odd name resolution rules fumbling requests.
Ah ok, this is my work machine. I took a look at /etc/hosts and saw ~200 routes defined that I didn't realize were there
As mention in the comments, this does not explain the odd behavior replicated using curl.
I've recently encountered a similar issue with slow connections from requests to 'localhost', and also found that using '127.0.0.1' was much faster.
After some investigation, I found that in my case, the slow connections on Windows were related to urllib3 (the transport library used by requests) attempting an IPv6 connection first, which is refused since the server is listening on IPv4 only. For Windows only, however, there is an unavoidable 1 sec timeout on socket.connect for refused TCP connections, while the OS 'helpfully' retries the connection up to 3 times. (See: Why do failed attempts of Socket.connect take 1 sec on Windows?).
On Linux, socket.connect fails immediately if the connection is refused, and it can attempt the IPv4 connection without any delay. In addition, some software, like curl, support limiting name resolution to only IPv4 or IPv6. Unfortunately, requests and urllib3 do not support this, and do not seem to plan to support this anytime soon (See: https://github.com/psf/requests/issues/1691)
For those trying to figure this out as no one gave a clear solution here:
I encountered this issue a while ago, and noticed that the Flask test server is not concurrent. The Python Requests takes FOREVER to retrieve the data from your flask app unless you make it concurrent. Enabling "Threaded" in your app.run option will do the trick!
app.run(port=5000, debug=True, threaded=True)

printing URL parameters of a HTTP request using Python + Nginx + uWSGI

I have used this link and successfully run a python script using uWSGI. Although i just followed the doc line by line.
I have a GPS device which is sending data to a remote server. Document of the same device say that it connect to server using TCP which therefore would be http as simple device like a GPS device would not be able to do https (i hope i am right here.) Now as i have configure my Nginx server to forward all incoming HTTP request to python script for processing via uWSGI.
What i want to do is to simply print the url or query string on the HTML page. As i don't have control on the device side (i can only configure device to send data on a IP + Port), i have no clue how data is coming. Below is my access log
[23/Jan/2016:01:50:32 +0530] "(009591810720BP05000009591810720160122A1254.6449N07738.5244E000.0202007129.7200000000L00000008)" 400 172 "-" "-" "-"
Now i have look at this link on how to get the url parameters values, but i don't have a clue that what is the parameter here.
I tried to modified my wsgi.py file as
import requests
r = requests.get("http://localhost.com/")
# or r = requests.get("http://localhost.com/?") as i am directly routing incoming http request to python script and incoming HTTP request might not have #any parameter, just data #
text1 = r.status_code
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return ["<h1 style='color:blue'>Hello There shailendra! %s </h1>" %(text1)]
but when i restarted nginx, i get internal server error. Can some one help me to understand wrong i am doing here (literally i have no clue about the parameters of the application function. Tried to read this link, but what i get from here is that environ argument take care of many CGI environment variables.)
Can some one please help me to figure out what wrong am i doing and guide me to even a doc or resource.
Thanks.
why are you using localhost ".com" ?
Since you are running the webserver on the same machine,
you should change the line to
r = requests.get("http://localhost/")
Also move below lines from wsgi.py and put them in testServerConnection.py
import requests
r = requests.get("http://localhost/")
# or r = requests.get("http://localhost.com/?") as i am directly routing incoming http request to python script and incoming HTTP request might not have #any parameter, just data #
text1 = r.status_code
Start NGINX
and you also might have to run (i am not sure uwsgi set up on nginx)
uwsgi --socket 0.0.0.0:8080 --protocol=http -w wsgi
run testConnection.py to send a test request to localhost webserver and print the response
i got the answer for my question. Basically to process a TCP request, you need to open a socket and accept the TCP request on a specific port (as you specified on the hardware)
import SocketServer
class MyTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
# self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip()
print "{} wrote:".format(self.client_address[0])
#data which is received
print self.data
if __name__ == "__main__":
#replace IP by your server IP
HOST, PORT = <IP of the server>, 8000
# Create the server, binding to localhost on port 9999
server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
# Activate the server; this will keep running until you
# interrupt the program with Ctrl-C
server.serve_forever()
After you get the data, you can do any thing with the data. As my data format was shared in the GPS datasheet, i was able to parse the string and get the Lat and long out of it.

"The connection was reset" on web browsers when trying to connect to a localhost socket server

I am trying to make a server in python using sockets that I can connect to on any web browser. I am using the host as "localhost" and the port as 8888.
When I attempt to connect to it, the stuff I want to be shown shows up for a split-second, and then it goes away with the browser saying "The connection was reset".
I've made it do something very simple to test if it still does it, and it does.
Is there a way to stop this?
import time
import socket
HOST = "localhost"
PORT = 8888
def function(sck):
sck.send(bytes("test"),"UTF-8"))
sck.close()
ssck=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ssck.bind((HOST,PORT))
ssck.listen(1)
while True:
sck,addr=ssck.accept()
function(sck)
Probably the same problem as Perl: Connection reset with simple HTTP server, Ultra simple HTTP socket server, written in PHP, behaving unexpectedly, HTTP Server Not Sending Complete File To WGET, Firefox. Connection reset by peer?. That is you don't read the HTTP header from the browser but simply send your response and close the connection.
tl;dr
your function should be
def function(sck):
sck.send(bytes("HTTP/1.1 200 OK\n\n<header><title>test page</title></header><body><h1>test page!</h1></body>"),"UTF-8"))
sck.close()
With a server as simple as that, you're only creating a TCP socket.
HTTP protocols suggest that the client should ask for a page, something like:
HTTP/1.1 GET /somepath/somepage.html
Host: somehost.com
OtherHeader: look at the http spec
The response should then be:
HTTP/1.1 200 OK
some: headers
<header></header><body></body>

Categories

Resources