Closed rakeshpai closed 7 years ago
A quick study of the NodeJS documentation seems to show that both request
and response
objects may have a property called connection
on them that represents the underlying TCP/IP socket. One possible design for the function requested would be the addition of something similar. We would then have to augment the Espruino Socket
object with the ability to get the two IP addresses and ports associated with a connected TCP socket.
I think it'd be a good idea to see how this is handled in Node.js - as the IP isn't immediately available to Espruino it'd have to check, which would take time. I'd rather not do that for all cases, so we could definitely do with some function that would get the information as needed.
Also, this is something that could be a complete pain to implement across wifi/ethernet/etc.
Would just checking the 'Host' header in the HTTP request be useful for you at all?
@nkolban You are exactly right - the request has a reference to .connection
, which is an instance of net.Socket - the underlying socket. The socket object represents a TCP socket, so it has its local IP and remote IP as its properties.
The Host header could work for a quick-and-dirty prototype, but headers are easy to fake, so it doesn't give the warm fuzzy feeling of being robust and correct. The IP would be much better, IMHO.
If there's an overhead involved in getting these parameters, we could structure the API such that you get this data only through a function call, as @gfwilliams suggested. The exact location of such a function in the object hierarchy would depend on where such an overhead is, so I'm probably not the best person to suggest. Interesting though, in node, the remote IP is a property (.remoteAddress
), whereas the local IP is a function (.address()
). Wonder what the story is behind that.
Thinking out loud, there's another possible solution at least to my problem at the moment, which isn't comprehensive, but is sufficient. If we could, instead of making the HTTP server bind to all network interfaces, could we get the HTTP server to bind to a specific interface? So when I call .listen()
on a http.createServer
instance, I could specify which interface it should bind to. This is how node does it - the hostName
is optional. When specified, it binds to just that specific IP. When not specified, it binds to all interfaces. The latter is what espruino currently does already, and we could consider implementing the former.
This does open a can of worms though, because we'd now need a way to get a list the current IPs, which will require it's own API. We've been discussing the common WiFi API on the wiki, and we've been thinking of having a .getIPs()
or similar call there. However, on second thoughts, for correctness, getting IPs shouldn't be a method on WiFi, but of the "networking subsystem", since we might also potentially have Ethernet, and who knows, maybe 6lowpan, all of which are TCP/IP networks. This what node does with its net
module. This is where the sockets get created and bound, and where TCP-level details are managed. So, this is where, for example, TLS would go.
I'd argue that all these changes are the "correct" thing to do. It will be some work, but it appears at first glance that we can do all of this in a backwards compatible fashion. For example, .getIPs
can live as a member of net
(in node, it is a member of os
), the Socket
class could expose new props/methods to get local and remote addresses, and the creating of servers could take a hostname as an argument. All of these are additive changes, and so are API-backward-compatible.
Sorry for rambling on, but there's my 2c. :)
Just realised that there's a eth.getIP
and a wlan.getIP
in the docs. Would it make sense to start thinking about an ap
object with ap.getIP
, or something along those lines?
In the wiki page for the new network interface, there was talk of a networkInterfaces
or similar, that should handle the AP and normal cases?
I mentioned that that's how node does it, but if there has been a discussion about doing a similar thing here, I'm not aware of it. I mentioned that in the context of the WiFi object, but I hadn't considered ethernet and 802.15.4, so I'm not sure anymore that it makes sense to add it to WiFi
.
Node has networkInterfaces
as a function, on their os
object, which seems to be a catch-all object to describe the system. Any thoughts about where this could live in Espruino's API?
Not sure what is expected here, so added this sample
// My IP is 192.168.194.121
var http = require("http");
var server = http.createServer(function (req, res) {
console.log("connect...");
console.log('req.headers:',req.headers);
res.writeHead(200);
res.end('<html><body><H1>Hello World</H1></body></html>');
});
server.listen(8080);
Test case A:
curl 192.168.194.121:8080
//output
connect...
req.headers: {
"Host": "192.168.194.121:8080",
"User-Agent": "curl/7.51.0",
"Accept": "*/*"
}
Test case B:
curl -H "host: 192.168.194.101:8080" 192.168.194.121:8080
//output
req.headers: {
"Host": "192.168.194.121:8080",
"User-Agent": "curl/7.51.0",
"Accept": "*/*"
}
If you want to get the ip of the caller, than make sure that the caller is sending this information like in test case B, otherwise you get the called server ip like in test case A
@gfwilliams I guess this issue can be closed.
Yes, closing... That's a really good solution - just checking Host
to see what the page has been requested on
It appears that the current
request
object available in thehttp.createServer
handler doesn't provide the client's IP address. Could we start providing this in the request object?My use-case is this: When the device (esp8266 in my case, but could be other boards) starts an http server, it seems to "bind" (in the linux sense) to all available network interfaces. This means that requests could come from different kinds of users:
it doesn't seem possible currently to distinguish between the two. I'm hoping I could use the octets in the IP address of the request to determine which network the request is coming from, so that I can serve different content to them.