May I inquire as to whether it is possible to obtain the IP address of the user?

I aim to record the IP address of users, which can be easily achieved in Shiny using the following code. However, I am uncertain how to accomplish this in Panel. Please forgive me if I have overlooked anything.

tags$script('$(document).on("shiny:sessioninitialized",function(){$.get("https://api.ipify.org", function(response) {Shiny.setInputValue("getIP", response);});})')
1 Like

Yes.

First, configure X-Forwarded-For in NGINX.

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

Then, get the IP in the panel app via:

doc.session_context.request.headers.get('X-Forwarded-For').split(", ")[:-2]

2 Likes

Hi @liuzj039

Welcome to the community :partying_face:

You can also build an IPAddress component using javascript, an external ip service and Panels ReactiveHTML.

Here is an example using the ipify service that your Shiny example also uses. I don’t know if this service is good or secure. But it works technically for me.

import panel as pn
import param

from panel.reactive import ReactiveHTML

class IPAddress(ReactiveHTML):
    value = param.String("", label="IP Adresss")

    _template = """<div id="ip-address"></div>"""

    _scripts = {
        "render": """
fetch('https://api.ipify.org/?format=json')
  .then(response => response.json())
  .then(json => {
    data.value = json.ip
  })
  .catch(error => {
    console.error('Error:', error);
  });
"""
    }

    def __init__(self, **params):
        # The IPAddress needs to be included in your layout or template
        # But we want it to be invisible
        params["height"]=params["width"]=params["margin"]=0
        super().__init__(**params)

if pn.state.served:
    pn.extension(template="bootstrap")
    
    ip_address = IPAddress()

    @pn.depends(ip_address.param.value)
    def show_ip_adress(value):
        if not value:
            return pn.Row(pn.indicators.LoadingSpinner(value=True, height=25, width=25, align="center"), f"# Requesting client IP address")
        print(value)
        return "# The client IP address arrived. Its xxx.xx.xxx.xxx (a secret)"

    pn.Column(
        ip_address, show_ip_adress
    ).servable()

show-client-ip

Please let me know if this works for you and if you have ideas for making this easier with Panel.

Please note it will sometimes take some time before ipify responds with the ip address.

1 Like

Thank you both for your kind responses, this is exactly what I needed!

2 Likes