How to get the IP address of a client using aiohttp - python

I am currently working on a django project where I use aiohttp to communicate between the backend and frontend. I wanted to get the IP address of a client when a request is made from the frontend. Looked in different docs but none seems to point to exactly how to get the IP address using aiohttp. Someone Help!
from aiohttp import web
async def handler(request):
ws = web.WebSocketResponse()
await ws.prepare(request)
try:
async for msg in ws:
# handle incoming messages
# use ws.send_str() to send data back
...
finally:
task.cancel()

Based on the aiohttp docs you can get the originating IP address of a client initiated HTTP request from requests remote parameter (request.remote).

Related

Porting a Websocket connection from a (game) website to python

There is some game that communicates with the server via a Websocket connection. I want to simulate this connection in python. When I click on the link, in the network tab, I see these connections: Image.
I copy the first message that the client sends in base64 format and try to reproduce it in code:
import asyncio, base64
from websockets import connect
URL = "wss://c7.eu.tankionline.com:9090/"
MSG_1 = base64.b64decode("ACoAA1TOlEGHY2d6XOx8gfqrE53STCBraCMoiOob+n2N6U10AAAAAAX2kcw=")
async def setup():
async with connect(URL) as websocket:
await websocket.send(MSG_1)
resp = await websocket.recv()
print(resp)
asyncio.run(setup())
But there is no response from the server. Why is that?

Python websockets vs websocket

I'm connecting to the same websocket address but for some reason I can't receive data using websockets+asyncio.
However, it does work when using websocket as well as using a raw websocket connection with Postman.
if SOCKET is the address
Using websockets + asyncio
import asyncio
import websockets
SOCKET = 'wss://api...'
async def handle(uri):
async with websockets.connect(uri) as websocket:
while True:
print(await websocket.recv())
asyncio.get_event_loop().run_until_complete(handle(SOCKET))
Using websocket
from websocket import create_connection
ws = create_connection(SOCKET)
while True:
try:
result = ws.recv()
print(result)
Does anyone know what can possibly be wrong with the first option? I'm actually following a python sample request suggested by a site's documentation when using websockets+asyncio.

python/ websocket implementation of sending messages to the client that keeps the socket open

Help me figure out how to implement it correctly.
The bottom line: The client is charging stations that connect, open a socket and send messages to the server and receive responses.
Server - listens to the port, sees the connected station, receives messages and sends responses to them.
Question: When the client connects and sends headers, I can send a message to the client. But I need to periodically send messages to the client that keeps the socket open, I don't understand how to implement this. Can someone tell me?
sample sending code:
charge_point_id = path.strip('/')
cp = client_main(charge_point_id, websocket)
logging.info(charge_point_id)
print(charge_point_id)
print(path)
await websocket.send(json.dumps([2,"222", "GetLocalListVersion", {}]))
await cp.start()
example of receiving a message from a client:
class client_main(cp):
errors = False
if not errors:
#on('BootNotification')
def on_boot_notitication(self, charge_point_vendor, charge_point_model,charge_point_serial_number,firmware_version,
meter_type, **kwargs):
return call_result.BootNotificationPayload(
status="Accepted",
current_time=date_str.replace('+00:00','Z'),
interval=60
)
in this case, the charging station according to the ocpp protocol opens the connection and keeps it open, it should be possible to somehow write to him
how do i send a message to the client? My example:
#on('Heartbeat')
def on_getlocallistversion(self):
await self.route_message(json.dumps([2,"222","GetLocalListVersion",{}]))
def on_hearbeat(self):
return call_result.HeartbeatPayload(
current_time=datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S')+"Z"
)
I get an error:
await self.route_message(json.dumps([2,"222",
"GetLocalListVersion",{}]))
This is impossible to do. You can send a message only when the client is connected.

Python - Unidirectional websocket

I'm trying to create a unidirectional websocket connection between the client and server (python). The libraries I've currently been prototyping with are websockets and simplesocketserver. I've got a hello world example getting from the server to the client, but I need to be able to send data from the backend to the client unprompted from the client. All of the websockets examples seem to show the server listening to the client and then responding.
So far I've tried:
Using websockets 8.0, sending data from server to client unprompted, this works but only with hard-coded strings, I don't understand how to send real data on demand unprompted from the client
Using simplesocketserver in the same exact manner
Started investigating server sent events - is this more appropriate?
Example from the websockets documentation:
import asyncio
import websockets
async def hello(websocket, path):
name = await websocket.recv()
print(f"< {name}")
greeting = f"Hello {name}!"
await websocket.send(greeting)
print(f"> {greeting}")
start_server = websockets.serve(hello, "localhost", 8765)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
Note: the need for unidirectional communication is due to existing architecture.
Any guidance or resources on this would be great, I hope I'm overlooking something easy. Thank you!
I came across a similar issue. After some trial and error I found a solution that works for me, maybe so it does for you. I've tested this on Linux and with Firefox and mobile Safari (parallel).
The InputThread waits for input (words) on the command line and writes them into a list, that is sent to all connected clients each time a new string is appended or a client is connected.
Code snippet
import asyncio
import websockets
import json
from threading import Thread
words = []
clients = []
async def register_client(websocket, path):
# register new client in list and keep connection open
clients.append(websocket)
await send_to_all_clients()
while True:
await asyncio.sleep(10)
async def send_to_all_clients():
global words
for i, ws in list(enumerate(clients))[::-1]:
try:
await ws.send(json.dumps({"words": words}))
except websockets.exceptions.ConnectionClosedError:
# remove if connection closed
del clients[i]
class InputThread(Thread):
def run(self):
global words
async def sending_loop():
while True:
i = input()
if not i.strip():
continue
words.append({"options": i.strip().slit()})
await send_to_all_clients()
asyncio.run(sending_loop())
InputThread().start()
asyncio.get_event_loop().run_until_complete(
websockets.serve(register_client, "localhost", 8765))
asyncio.get_event_loop().run_forever()

How can I connect with address using asyncio open_connection function

I would like to connect with several address using asyncio library, like
'127.0.0.1:8000/hello'
But where can I put '/hello' part ? and how can I call this part? (endpoint? static url? )
asyncio.open_connection('127.0.0.1', 8000)
But where can I put /hello part ?
asyncio.open_connection opens a raw TCP connection to the given remote endpoint. The address of the form 127.0.0.1:8000/hello strongly indicates an HTTP connection. HTTP is a protocol built on top of TCP, where you connect to the given host and port (127.0.0.1 and port 8000 in your case) using TCP and send a request in a specified format, and to which the server answers with a response.
HTTP communication is a complex topic and is not something you want to implement from scratch. Fortunately there are mature asyncio-aware libraries that handle it for you, such as aiohttp. Using that library connecting to a server might look like this:
import aiohttp, asyncio
async def connect_to(url, session):
async with session.get(url) as response:
return await response.data()
async def main():
async with aiohttp.ClientSession() as session:
data = connect_to('http:/127.0.0.1:8000/hello')
# do something with data, or connect to other urls
asyncio.run(main())
and how can I call this part? (endpoint? static url? )
That part is typically called the path of the URL, see e.g. section 3.3 of the RFC for more details.

Categories

Resources