duanmeng9336 2016-08-29 22:19
浏览 141
已采纳

如何在Go-restful中获得完整的主机和URL

I'm writing a REST API in Go using https://github.com/emicklei/go-restful

In my JSON output I want to output absolute path to other REST resources, but I don't know how I can obtain all the relevant parts to build the Path, such as transport (http/https), host, port, root path.

Do I need to keep track of this myself, do I fetch it from the Request somehow?

  • 写回答

1条回答 默认 最新

  • doucheng1944 2016-08-30 00:32
    关注

    After playing with this for a while, I ended up trying it both ways. It turns out that at least some of the information can be extracted from Request (note: I presume that if the route were defined with an absolute url then all of this information could be had from Request.URL)

    package main
    
    import (
        "github.com/emicklei/go-restful"
        "io"
        "net/http"
    )
    
    func main() {
        ws := new(restful.WebService)
        ws.Route(ws.GET("/hello").To(hello))
        restful.Add(ws)
        http.ListenAndServe(":8080", nil)
    }
    
    func hello(req *restful.Request, resp *restful.Response) {
        io.WriteString(resp, "Protocol: " + req.Request.Proto + "
    Host: " + req.Request.Host + "
    Path: " + req.Request.URL.Path)
    }
    

    The above prints the following to the browser. I suppose one could use this to construct urls to jsonify, although it's not clear how the base path would be parsed out without some prior knowledge of either the base path or the specific path, or some syntactic convention for distinguishing the two.

    Protocol: HTTP/1.1
    Host: localhost:8080
    Path: /hello
    

    The second thing I tried was to define a URL at package level and use that to build a custom parse function. url.URL maintains a struct representation of a URL; A relative (or absolute) path can be parsed and merged with an existing URL using URL.parse(string). Conveniently, URL can output a string representation of itself via it's String() method.

    The custom parse function simply holds on to a copy of the package level URL, and each time it is called with some specific path it pastes the new path on to the end of the URL.Path and returns a new URL that's identical except for the new concatenated path (because that's what URL.parse() does when we hand it a relative path). URL.String() can then be called on the new URL to stringify the URL into the string that we want to marshal.

    package main
    
    import (
        "github.com/emicklei/go-restful"
        "io"
        "net/http"
        "net/url"
        "fmt"
        "encoding/json"
    )
    
    var myurl = url.URL{
    Scheme:"http",
    Host: "localhost:8080",
    Path:"basepath",
    }
    
    var parse = getParseFn(myurl)
    
    func main() {
        ws := new(restful.WebService)
        ws.Route(ws.GET("/jsonUrls").To(jsonUrls))
        restful.Add(ws)
        http.ListenAndServe(":8080", nil)
    }
    
    func jsonUrls(req *restful.Request, resp *restful.Response) {
        urls := []string{}
        for _, s := range []string{"get", "put", "whatever"} {
            u, err := parse(s)
            if err != nil {
                fmt.Println(err)
            }
            urls = append(urls, u.String())
        }
        json_urls, err := json.Marshal(urls)
        if err != nil {
            fmt.Println(err)
        }
        io.WriteString(resp, string(json_urls))
    }
    
    func getParseFn (myUrl url.URL) func (string) (*url.URL, error) {
        parse := func (s string) (*url.URL, error) {
            u, err := myUrl.Parse(myUrl.Path + "/" + s)
            return u, err
        }
        return parse
    } 
    

    This prints the following in the browser:

    ["http://localhost:8080/basepath/get","http://localhost:8080/basepath/put","http://localhost:8080/basepath/whatever"]
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 微信会员卡等级和折扣规则
  • ¥15 微信公众平台自制会员卡可以通过收款码收款码收款进行自动积分吗
  • ¥15 随身WiFi网络灯亮但是没有网络,如何解决?
  • ¥15 gdf格式的脑电数据如何处理matlab
  • ¥20 重新写的代码替换了之后运行hbuliderx就这样了
  • ¥100 监控抖音用户作品更新可以微信公众号提醒
  • ¥15 UE5 如何可以不渲染HDRIBackdrop背景
  • ¥70 2048小游戏毕设项目
  • ¥20 mysql架构,按照姓名分表
  • ¥15 MATLAB实现区间[a,b]上的Gauss-Legendre积分