如何在HttpHandler(Julia语言)中获取客户端IP地址?

Vla*_*dev 2 http httpserver julia

我需要在常规的HttpHandler中获取客户端的IP地址,如下所示:

http = HttpHandler() do req::Request, res::Response
    Response( ismatch(r"^/hello/",req.resource) ? string("Hello ", split(req.resource,'/')[3], "!") : 404 )
end
Run Code Online (Sandbox Code Playgroud)

既不包含req也不http.sock包含此信息.

waT*_*eim 5

该方法

如果你知道朱莉娅的内部一点,这可以做到.事实证明,Julia使用库libuv进行低级系统处理,并且该库有一个名为uv_tcp_getpeername的函数.Julia.Base不会导出此函数,但您可以通过ccall访问它.此外,模块HttpServer允许为各种事件定义回调,包括connect事件.

示例模块

module HTTPUtil
   export get_server
   using HttpServer

   function handle_connect(client)
      try
         buffer = Array(Uint8,32)
         bufflen::Int64 = 32

         ccall(:uv_tcp_getpeername,Int64,(Ptr{Void},Ptr{Uint8},Ptr{Int64}),client.sock.handle,buffer,&bufflen)

         peername::IPv4 = IPv4(buffer[5:8]...)
         task_local_storage(:ip,peername)
      catch e
         println("Error ... $e")
      end
   end

   function get_server()
      http = HttpHandler() do req::Request, res::Response
         ip = task_local_storage(:ip)
         println("Connection received from from $ip")
         Response(ismatch(r"^/hello/",req.resource)?string("Hello ",split(req.resource,'/')[3], " $(ip)!") : 404 )
      end

      http.events["connect"]=(client)->handle_connect(client)
      server = Server(http)
   end
end
Run Code Online (Sandbox Code Playgroud)

解释

每次发出连接请求时,服务器都会创建一个对等套接字,并调用connect处理程序,该处理程序被定义为handle_connect.它需要一个Client类型的参数client .甲客户端类型有一个称为字段短袜的TCPSocket,和一个的TCPSocket具有场手柄,其使用libuv.然后,对象是每次发出连接请求时,都会调用connect处理程序,它使用TcpSocket句柄中包含的数据调用uv_tcp_getpeername.声明一个字节数组充当缓冲区,然后将其转换回Base.IPv4.模块HTTPServer 使用@async为每个客户端创建正好1个任务,因此可以使用task_local_storage将ip地址存储在客户端本地 ; 因此没有竞争条件.

使用它

julia> using HTTPUtil
julia> server = get_server()
Server(HttpHandler((anonymous function),TcpServer(init),Dict{ASCIIString,Function} with 3 entries:
  "error" => (anonymous function)
  "listen" => (anonymous function)
  "connect" => (anonymous function)),nothing)

julia> @async run(server,8000)
Listening on 8000...
Task (queued) @0x000000000767e7a0

julia> Connection received from from 192.168.0.23
Connection received from from 192.168.0.22
... etc
Run Code Online (Sandbox Code Playgroud)

笔记

  1. 为了说明,输出被修改,以便服务器将响应每个浏览器"Hello ipaddr "
  2. 这应该包含在Base和/或HttpServer中,但目前不包括在内,因此您需要使用此解决方法,直到它为止.
  3. get_server中使用典型的循环结构来说明除了添加ip地址之外不需要更改它.
  4. 假设IPv4,但可以改进以直接允许IPv4和IPv6,因为libuv支持两者.