如何使用net/http获取服务器在服务器中的自身地址? [英] How to get Server's own address in a server using net/http?

查看:111
本文介绍了如何使用net/http获取服务器在服务器中的自身地址?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用Go的net/http包编写一个HTTP服务器,其响应取决于HTTP连接的服务器端IP地址.

I would like to write a HTTP server using the Go's net/http package, with the reaction that would depend on server side IP address of the HTTP connection.

换句话说,我正在寻找的等效于CGI的"SERVER_ADDR"变量.

In other words, what I am looking for is equivalent of CGI's "SERVER_ADDR" variable.

http.Request中最接近的字段是主机"-但由于仅在请求使用文字地址时它才等于地址,因此我无法使用它(服务器可能按名称使用).

The closest field in http.Request is "Host" - but since it will only be equal to an address if the request uses a literal address, I can not use it (the server might be used by name).

> https://golang.org/src/net/http/server.go ,似乎到达服务器地址的唯一方法是在处理程序中建立Hijack()连接,并为同一连接上的后续请求实现后续HTTP解析,但是这样做似乎非常不明智至少要说...

Looking at the sources at https://golang.org/src/net/http/server.go, seems the only way to get to the server's address is to Hijack() the connection within a handler and implement subsequent HTTP parsing for the subsequent requests on the same connection, but it looks very inelegant to say the least...

似乎理想的解决方案是对golang标准库中的http/request和http/server进行如下修改:

It seems like the ideal solution would be to have the http/request and http/server in the golang standard library modified as follows:

diff -u go-stock-library/request.go ./request.go
--- go-stock-library/request.go 2016-04-13 17:31:48.000000000 +0200
+++ ./request.go    2016-04-13 17:32:40.000000000 +0200
@@ -227,6 +227,15 @@
    // This field is ignored by the HTTP client.
    RemoteAddr string

+   // LocalAddr allows HTTP servers and other software to record
+   // the network address that the request was sent to, usually for
+   // logging. This field is not filled in by ReadRequest and
+   // has no defined format. The HTTP server in this package
+   // sets LocalAddr to an "IP:port" address before invoking a
+   // handler.
+   // This field is ignored by the HTTP client.
+   LocalAddr string
+
    // RequestURI is the unmodified Request-URI of the
    // Request-Line (RFC 2616, Section 5.1) as sent by the client
    // to a server. Usually the URL field should be used instead.
diff -u go-stock-library/server.go ./server.go
--- go-stock-library/server.go  2016-04-13 17:29:19.000000000 +0200
+++ ./server.go 2016-04-13 17:31:38.000000000 +0200
@@ -161,6 +161,13 @@
    // This is the value of a Handler's (*Request).RemoteAddr.
    remoteAddr string

+   // serverAddr is rwc.LocalAddr().String(). It is not populated synchronously
+   // inside the Listener's Accept goroutine, as some implementations block.
+   // It is populated immediately inside the (*conn).serve goroutine.
+   // This is the value of a Handler's (*Request).LocalAddr.
+   localAddr string
+   
+
    // tlsState is the TLS connection state when using TLS.
    // nil means not TLS.
    tlsState *tls.ConnectionState
@@ -736,6 +743,7 @@
    delete(req.Header, "Host")

    req.RemoteAddr = c.remoteAddr
+   req.LocalAddr = c.localAddr
    req.TLS = c.tlsState
    if body, ok := req.Body.(*body); ok {
        body.doEarlyClose = true
@@ -1382,6 +1390,7 @@
 // Serve a new connection.
 func (c *conn) serve() {
    c.remoteAddr = c.rwc.RemoteAddr().String()
+   c.localAddr = c.rwc.LocalAddr().String()
    defer func() {
        if err := recover(); err != nil {
            const size = 64 << 10

,然后以一种简洁的方式在代码中使用新的LocalAddr.

and then use the new LocalAddr in the code in a nice and clean way.

是否有一种更清洁的方法?

Is there a cleaner way to do this?

推荐答案

我个人不会修改标准库中的任何内容,而可以通过其他方式获得.从每个连接中解析出来是否有一些优势?

I personally wouldn't modify anything in the standard library for something I could get other ways. Is there some advantage to parsing it out of every connection?

可能有一种更简单的方法,但是我有以下内容.

There is probably a simpler way, but I have the following.

func getMyInterfaceAddr() (net.IP, error) {


    ifaces, err := net.Interfaces()
    if err != nil {
        return nil, err
    }
    addresses := []net.IP{}
    for _, iface := range ifaces {

        if iface.Flags&net.FlagUp == 0 {
            continue // interface down
        }
        if iface.Flags&net.FlagLoopback != 0 {
            continue // loopback interface
        }
        addrs, err := iface.Addrs()
        if err != nil {
            continue
        }

        for _, addr := range addrs {
            var ip net.IP
            switch v := addr.(type) {
            case *net.IPNet:
                ip = v.IP
            case *net.IPAddr:
                ip = v.IP
            }
            if ip == nil || ip.IsLoopback() {
                continue
            }
            ip = ip.To4()
            if ip == nil {
                continue // not an ipv4 address
            }
            addresses = append(addresses, ip)
        }
    }
    if len(addresses) == 0 {
        return nil, fmt.Errorf("no address Found, net.InterfaceAddrs: %v", addresses)
    }
    //only need first
    return addresses[0], nil
}

这篇关于如何使用net/http获取服务器在服务器中的自身地址?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆