2017-04-09 51 views
2

我編寫了一個簡單的網絡服務器,獲取給定URL的內容並使用http.ResponseWriter將其寫出。但問題是它不會在頁面上顯示任何圖像和CSS。代碼如下:返回給定網址內容的網絡服務器

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) 
} 

我需要更改哪些內容以便在瀏覽器中看到整個頁面內容?

回答

0

TL; DR

  • 你只提供根HTML頁面,則需要到請求到其他資源過於迴應(你可以通過* http.Request變量的URL變量來查看正在請求的資源)

  • 當提供資源時,您需要編寫Header Content-Type讓瀏覽器知道什麼是

    你在做什麼在你的請求處理程序越來越http://www.meaningfultype.com/,HTML頁面,然後在瀏覽器發現的資源(如image/png

完整的答案的類型像/images/header-logo.png圖像,並提出請求,但您的localhost服務器不知道如何迴應http://localhost/images/header-logo.png

假設你的處理函數是在服務器("/")的根處理請求,你可以得到所請求的URL r.URL,並用它來獲得所需的資源:

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

的問題是,即使完成此操作後,所有資源將以plain/text發送,因爲您未設置標題的Content-Type。這就是爲什麼你需要在寫入之前指定資源的類型。爲了知道什麼資源的類型,只是從在http.Get響應報頭中的Content-Type您剛剛收到獲得它:

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

最終結果:

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) 
} 

+0

由於它的工作爲了我。 –

+0

如果在示例中給出的URL不能修復,如何管理它。我想給任何URL在瀏覽器等給出波紋管: 的http://本地主機:8080/fastor/TTP://www.meaningfultype.com/ –

+1

你只需要到'url'變量設置爲正確的值。變量'r.URL'包含用戶請求的URL(在本例中爲http:// localhost:8080/fastor/http://www.meaningfultype.com/),所以你只需要移除http:// localhost:8080/fastor /',並使用剩餘的字符串作爲url的值,但請記住,雙斜線將被一個斜線替換,因此路徑中的URL將變爲http:/www.meaningfultype。 com'不要將路徑包含在路徑中並手動添加到字符串中可能會更好。 – raulsntos

2

這裏的問題大概是你引用的網站使用圖像和樣式表的相對路徑,例如, "/css/main.css"。您使用Go服務提供給瀏覽器的本地網站有另一個域(例如localhost),因此瀏覽器無法解析相對路徑(沒有http://localhost/css/main.css)。

因此,您需要做的是在您交付的文檔中設置基本URL,或者將每個相對路徑重寫爲絕對路徑(/css/main.csshttp://originalwebsite.com/css/main.css)。

要在文檔中添加基本標記或重寫URL,我建議使用類似goquery的東西,它可以讓您操作類似於jQuery的HTML結構。加入<base>標籤的

例子:

import (
    "github.com/PuerkitoBio/goquery" 
    "fmt" 
) 

func main() { 
    doc,err := goquery.NewDocument("http://www.meaningfultype.com/") 

    if err != nil { 
     panic(err) 
    } 

    m := doc.Find("head") 

    m.Children().First().BeforeHtml(`<base url="http://localhost/">`) 

    fmt.Println(doc.Html()) 
}