How to get client IP address using python bottle framework - python

I need client IP address using python. I have tried below code but its not working in server:
from socket import gethostname, gethostbyname
ip = gethostbyname(gethostname())
print ip
On the server, I get '127.0.0.1' every time. Is there any way to find IP address of the client?

You're getting the IP address of your server, not of your server's clients.
You want to look at the request's REMOTE_ADDR, like this:
from bottle import Bottle, request
app = Bottle()
#app.route('/hello')
def hello():
client_ip = request.environ.get('REMOTE_ADDR')
return ['Your IP is: {}\n'.format(client_ip)]
app.run(host='0.0.0.0', port=8080)
EDIT #1: Some folks have observed that, for them, the value of REMOTE_ADDR is always the same IP address (usually 127.0.0.1). This is because they're behind a proxy (or load balancer). In this case, the client's original IP address is typically stored in header HTTP_X_FORWARDED_FOR. The following code will work in either case:
#app.route('/hello')
def hello():
client_ip = request.environ.get('HTTP_X_FORWARDED_FOR') or request.environ.get('REMOTE_ADDR')
return ['Your IP is: {}\n'.format(client_ip)]
EDIT #2: Thanks to #ArtOfWarfare's comment, I learned that REMOTE_ADDR is not required per PEP-333. Couple of observations:
The CGI spec does require REMOTE_ADDR:
The REMOTE_ADDR variable MUST be set to the network address of the client sending the request to the server.
However, PEP-333 does not explicitly require HTTP_REMOTE_ADDR, only going as far as this (emphasis mine):
A server or gateway SHOULD attempt to provide as many other CGI variables as are applicable.
All of the (admittedly few) web frameworks that I'm familiar with set HTTP_REMOTE_ADDR. AFAICT, it's a de facto "standard." But technically, YMMV.

Server might be behind a proxy. Use this for proxy and forward support:
request.environ.get('HTTP_X_FORWARDED_FOR') or request.environ.get('REMOTE_ADDR')

If you're trying to get the external IP, you will need to get it from an external source, i.e whatismyip.com or somewhere that offers an api. If that's what you're looking for, take a look at the Requests module http://docs.python-requests.org/

Related

How to get the IP of the default interface with Sanic

Is it possible to get the IP of the default interface with Sanic?
Here is how I do it with Socket. The idea is to do the same thing with Sanic.
import socket
hostname = socket.gethostname()
IP_address = socket.gethostbyname(hostname)
print(IP_address) # 192.168.1.239
It depends upon what information you want and how the app is being served (reverse proxy, etc).
Check out these values:
request.ip (connected interface)
request.remote_addr (likely what you want https://sanic.readthedocs.io/en/stable/sanic/api/core.html#sanic.request.Request.remote_addr)
request.conn_info (object with a bunch of details you may want)

How to make Python HTTP server have custom url instead of localhost?

I'm using the HTTP server module in Python 3 and I want to make my local HTTP server have a custom url instead of "localhost:8080". Is there any way for me to do this in Python alone without changing default OS settings like the settings in the host file?
When you can setup your router, you must make a port-forwarding. (You usually can setup it on http://192.168.0.1/)
Then you can use that url: "http:// Your Global IP:8080/" for example, when my global IP address is 4.4.0.0, than "http://4.4.0.0:8080/".
When you use the port 80 instead of 8080 (you can setup in port forwarding), it is the professional port of http server, your url will be (with the last example ip): "http://4.4.0.0/"
You can see your global IP address for example on this page: https://whatismyipaddress.com/
or from python code:
gloval_IP = get('https://api.ipify.org').text

Python, Flask client ip address

I need to log the IP address of every user of my webapp, that I've created with Python and Flask.
I'm using
request.remote_addr
But that's return the IP address of the server the app is deployed to. Any fixes to this?
How do you deploy the flask application?
I guess you deploy your app via a reverse-proxy server like nginx, right?
If you did that then request.remote_addr is the address of your server because your server sent client's request to your application and sent the response to the client.
To fix this, see: http://flask.pocoo.org/docs/0.11/deploying/wsgi-standalone/#proxy-setups
The easiest way to get the user's(also known as client) IP is to set this as a variable or use it directly.
request.environ['REMOTE_ADDR']
To get your server's IP:
request.remote_addr

Flask server not visible from my public ip address

I'm trying to run a flask server on my desktop PC that is publicly available on the internet. I've done the following:
Set up a static IP address: 192.168.1.11 (http://i.imgur.com/Z9GEBYV.png)
Forwarded port 33 on my router to my static ip address (http://i.imgur.com/KGNQ2Qk.png)
Setup flask to use my static ip and port: 33
I'm using the following code as a test webserver
from flask import Flask, request, redirect
app = Flask(__name__)
#app.route("/")
def hello_world():
return "Test 123 "
if __name__ == "__main__":
app.run(host="0.0.0.0", port="33")
When I open my browser to: http://192.168.1.11:33/ the page displays properly, I see "Test 123"
My problem comes when trying to connect to my webserver from my public ip address When I open my browser to http://xx.xxx.xxx.xx:30 (my ip address) all I see is "this site can't be reached, xx.xxx.xxx.xx refused to connect"
I've looked up all the stack overflow answers, I've done the following:
Turned off windows firewall
Changed host from "192.168.1.11" to "0.0.0.0"
Tried a different port
screenshot of code running and error shown: http://i.imgur.com/a05GvEs.png
My question is: What do I need to do to make my flask server visible from my public ip address?
Do you have DHCP activated on your router?
If yes do you see your host as 192.168.1.11 in there?
You have to use '0.0.0.0' on host, that tells Flask to listen on all addresses.
Try specifying the port with quotes as app.run(host="0.0.0.0", port="33")
change it to app.run(host= '0.0.0.0', port="33") to run on your machines IP address.
Documented on the Flask site under "Externally Visible Server" on the Quickstart page:
http://flask.pocoo.org/docs/0.10/quickstart/#a-minimal-application
Add port forwarding to port 33 in your router
Port forwarding explained here
http://www.howtogeek.com/66214/how-to-forward-ports-on-your-router/
You must give the public ip address/LAN ip address as an argument to app.run method.
When you don't provide host argument, it works fine with http://localhost:8888/ and http://127.0.0.1:888/, but not to access outside the system where you are running the REST services
Following is the example.
app.run(host="192.168.0.29",debug=True, port=8888)
You must try and use the same ip of the development server. Thus, for instance, if the dev server is running on a PC with the address 192.168.1.11
and port 33, other clients must point at the same address: 192.168.1.11:33.
As far as my small experience, it works with the debugger disabled, but I did not check if this is an essential prerequisite.
good luck
Every webservice should be run from different port address.Single service is running from a single port.

get server address from bottle

Is it possible to get the IP Address of the server programmaticaly in a bottle request?
I need to return a link to a file on the server inside a request and need to know the IP. Bottle will be started on a server with different IPs and all of these IPs will be serve requests.
currently i looks like this:
from bottle import *
import json
#get('/file')
def getAFileLink():
# some logic here for the right filename to return
# server runs now on e.g. 10.0.0.1 and 10.10.0.1
# every client should see the IP from the server in the right subnet
return json.dumps({'url': 'http://127.0.0.1:1337/some/file.abc'})
#route('/some/<filename>')
def getStaticFile(filename):
return static_file(filename, root="/srv/static/files")
if __name__ == "__main__":
run(host='0.0.0.0', port=1337)
If your servers aren't behind a load balancer, just use the Host HTTP header.
#route('/file')
def getAFileLink():
host = bottle.request.get_header('host')
return {'url': 'http://{}/some/file.abc'.format(host)}
Give a try to bottle.request.url (docs).
In case you need only scheme and hostname, use urlparse to get it.
you can use:
from bottle import request
urlparts = request.urlparts
print urlparts.scheme
print urlparts.netloc
docs
Why are you running your server on the same ip as the link that you return?
import socket
socket.gethostbyname(socket.gethostname())

Categories