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包含此信息.
如果你知道朱莉娅的内部一点,这可以做到.事实证明,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)