douhuxi4145 2017-04-09 10:11
浏览 87
已采纳

返回给定URL内容的Web服务器

I wrote a simple web sever that gets the content of a given URL and writes it out using a http.ResponseWriter. But the problem is that it does not display any images and CSS on the page. The code is given bellow:

func factHandler(w http.ResponseWriter, r *http.Request) {
    res, err := http.Get("http://www.meaningfultype.com/")
    if err != nil {
        log.Fatal(err)
    }
    robots, err := ioutil.ReadAll(res.Body)

    res.Body.Close()
    if err != nil {
        log.Fatal(err)
    }   
    w.Write(robots)
}

What do I need to change so that the the whole page content as seen in the web browser is returned?

  • 写回答

2条回答 默认 最新

  • donglian1953 2017-04-09 11:41
    关注

    TL;DR

    • You are only serving the root HTML page, you need to respond to requests to other resources too (you can see what resource is being requested with the URL variable of the *http.Request variable)

    • When serving the resources, you need to write the Header's Content-Type to let the browser know what's the type of the resource (like image/png)

    Full Answer

    What you are doing in your request handler is getting http://www.meaningfultype.com/, the HTML page, then the browser finds an image like /images/header-logo.png and makes the request to get it but your server in localhost doesn't know how to respond to http://localhost/images/header-logo.png.

    Assuming your handler function is handling requests at the root of the server ("/"), you could get the requested URL r.URL and use it to get the required resource:

    url := "http://www.meaningfultype.com/"
    if r.URL.Host == "" {
        url += r.URL.String()
    } else {
        url = r.URL.String()
    }
    res, err := http.Get(url)
    

    The problem is that, even after doing this, all the resources are sent as plain/text because you are not setting the Header's Content-Type. That's why you need to specify the type of the resource before writing. In order to know what the type of the resource is, just get it from the Content-Type you just received in the Header of the response of http.Get:

    contentType := res.Header.Get("Content-Type")
    w.Header().Set("Content-Type", contentType)
    w.Write(robots)
    

    The final result:

    package main
    
    import (
        "io/ioutil"
        "log"
        "net/http"
    )
    
    func main() {
        http.HandleFunc("/", factHandler)
        http.ListenAndServe(":8080", nil)
    }
    
    func factHandler(w http.ResponseWriter, r *http.Request) {
        url := "http://www.meaningfultype.com/"
        if r.URL.Host == "" {
            url += r.URL.String()
        } else {
            url = r.URL.String()
        }
        res, err := http.Get(url)
        if err != nil {
            log.Fatal(err)
        }
        robots, err := ioutil.ReadAll(res.Body)
    
        res.Body.Close()
        if err != nil {
            log.Fatal(err)
        }
        contentType := res.Header.Get("Content-Type")
        w.Header().Set("Content-Type", contentType)
        w.Write(robots)
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 树莓派与pix飞控通信
  • ¥15 自动转发微信群信息到另外一个微信群
  • ¥15 outlook无法配置成功
  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题