Реализовать http-web-proxy
Автор: pravoved • Ноябрь 23, 2020 • Лабораторная работа • 2,281 Слов (10 Страниц) • 290 Просмотры
Цель: Реализовать http-web-proxy.
Исходный код программы:
package main
import (
"fmt"
"golang.org/x/net/html"
"golang.org/x/net/html/charset"
"html/template"
"log"
"net/http"
"strings"
)
var hostname string
type Item struct {
Address string
}
func downloadDoc(w http.ResponseWriter, url string) *html.Node {
doc, err := getDoc(url)
if err != nil {
w.Write([]byte(err.Error()))
return nil
}
return doc
}
func getDoc(url string) (*html.Node, error) {
r, err := http.Get(url)
if err != nil {
return nil, err
}
defer r.Body.Close()
utf8, err := charset.NewReader(r.Body, r.Header.Get("Content-Type"))
if err != nil {
return nil, err
}
node, err := html.Parse(utf8)
if err != nil {
return nil, err
}
return node, nil
}
func getChildren(node *html.Node) []*html.Node {
var children []*html.Node
for child := node.FirstChild; child != nil; child = child.NextSibling {
children = append(children, child)
}
return children
}
func getElemsByTag(node *html.Node, tag string) []*html.Node {
if node != nil {
nodes := make([]*html.Node, 0)
if node.Data == tag {
nodes = append(nodes, node)
}
for _, child := range getChildren(node) {
subNodes := getElemsByTag(child, tag)
if subNodes != nil {
nodes = append(nodes, subNodes...)
}
}
return nodes
}
return nil
}
func changeLink(doc *html.Node) {
links := getElemsByTag(doc, "link")
//fmt.Println("len =", len(links))
for _, link := range links {
for i, attr := range link.Attr {
if attr.Key == "href" {
href := attr.Val
//fmt.Println("href1="+href)
if !strings.Contains(href, hostname) {
if hostname[len(hostname) - 1] != '/' && href[0] != '/' {
href = hostname + "/" + href
} else {
href = hostname + href
}
strings.Replace(href, "//", "/", 1)
href = "http://" + href
}
//fmt.Println("href2="+href)
link.Attr[i].Val = href
}
}
}
}
func changeScript(doc *html.Node) {
links := getElemsByTag(doc, "script")
//fmt.Println("len =", len(links))
for _, link := range links {
for i, attr := range link.Attr {
if attr.Key == "src" {
href := attr.Val
//fmt.Println("href1="+href)
if !strings.Contains(href, "http://") {
if hostname[len(hostname) - 1] != '/' && href[0] != '/' {
href = hostname + "/" + href
} else {
href = hostname + href
}
strings.Replace(href, "//", "/", 1)
href = "http://" + href
}
//fmt.Println("href2="+href)
link.Attr[i].Val = href
}
}
}
}
func changeImg(doc *html.Node) {
links := getElemsByTag(doc, "img")
//fmt.Println("len =", len(links))
for _, link := range links {
for i, attr := range link.Attr {
if attr.Key == "src" {
href := attr.Val
//fmt.Println("href1="+href)
if !strings.Contains(href, "http://") && !strings.Contains(href, "https://") {
if hostname[len(hostname) - 1] != '/' && href[0] != '/' {
href = hostname + "/" + href
} else {
href = hostname + href
}
strings.Replace(href, "//", "/", 10)
href = "http://" + href
}
//fmt.Println("href2="+href)
link.Attr[i].Val = href
}
}
}
}
func changeA(doc *html.Node) {
links := getElemsByTag(doc, "a")
//fmt.Println("len =", len(links))
for _, link := range links {
for i, attr := range link.Attr {
if attr.Key == "href" {
href := attr.Val
//fmt.Println("href1="+href)
if !strings.Contains(href, "http://") {
if hostname[len(hostname) - 1] != '/' && href[0] != '/' {
href = hostname + "/" + href
} else {
href = hostname + href
}
strings.Replace(href, "//", "/", 1)
href = "http://" + href
} else {
href = "http://localhost:9607/" + strings.Split(href, "http://")[1]
}
//fmt.Println("href2="+href)
link.Attr[i].Val = href
}
}
}
}
func updateHostname(r *http.Request) {
adr := r.URL.String()
//fmt.Println("adr update = " +adr)
if adr[0] == '/' {
adr = adr[1:]
}
if strings.Contains(adr, "http://") {
adr = strings.Split(adr, "http://")[1]
}
if adr != "" {
hostname = strings.Split(adr, "/")[0]
}
//fmt.Println("update = " + hostname)
}
func Handler(w http.ResponseWriter, r *http.Request) {
url := r.URL.String()
if url == "/" || url == "/favicon.ico" {
tmpl, err := template.ParseFiles("index.html")
if err != nil {
log.Fatal(err)
}
adr := r.FormValue("addr")
if strings.Contains(adr, "http://") {
adr = strings.Split(adr, "http://")[1]
}
if adr != "" {
hostname = strings.Split(adr, "/")[0]
}
//fmt.Println("adr = " + hostname)
tmpl.Execute(w, Item { Address: adr } )
} else {
updateHostname(r)
var err error
var doc *html.Node
if url[0] == '/' {
url = url[1:]
}
//fmt.Println("url="+url, ", host="+hostname)
if !strings.Contains(url, hostname) &&
(strings.Contains(url, ".jpg") || strings.Contains(url, ".css") ||
strings.Contains(url, ".js") || strings.Contains(url, ".png") ||
strings.Contains(url, ".gif")) || strings.Contains(url, ".JPG") {
if hostname[len(hostname) - 1] != '/' && url[0] != '/' {
url = hostname + "/" + url
} else {
url = hostname + url
}
strings.Replace(url, "//", "/", 1)
}
if url[0] == '/' {
url = "http:/" + url
} else {
url = "http://" + url
}
//fmt.Println("url2="+url)
doc, err = getDoc(url)
if err != nil {
log.Fatal(err)
}
updateHostname(r)
changeLink(doc)
changeScript(doc)
changeImg(doc)
changeA(doc)
err = html.Render(w, doc)
if err != nil {
fmt.Println(err.Error())
}
}
}
func main() {
http.HandleFunc("/", Handler)
log.Fatal(http.ListenAndServe("localhost:9607", nil))
}
...