[fix] fix #14. Fetched URI matched the mortyurl.

Query parameters in requested URI were parsed and set again. Unfortunately a query ?a&b were changed into ?a=b= which can lead to 404 errors.

git-svn-id: file:///srv/svn/repo/yukari/trunk@44 f3bd38d9-da89-464d-a02a-eb04e43141b5
This commit is contained in:
alex 2016-11-28 09:59:14 +00:00
parent ce7aee2e64
commit f8623282a5

View File

@ -17,8 +17,7 @@ import (
"github.com/valyala/fasthttp"
"golang.org/x/net/html"
"golang.org/x/net/html/charset"
"golang.org/x/text/encoding"
"golang.org/x/text/encoding/charmap"
)
const (
@ -123,8 +122,6 @@ input[type=checkbox]#mortytoggle:checked ~ div { display: none; }
</style>
`
var HTML_META_CONTENT_TYPE string = "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">"
func (p *Proxy) RequestHandler(ctx *fasthttp.RequestCtx) {
if appRequestHandler(ctx) {
@ -166,18 +163,11 @@ func (p *Proxy) RequestHandler(ctx *fasthttp.RequestCtx) {
defer fasthttp.ReleaseRequest(req)
req.SetConnectionClose()
reqQuery := parsedURI.Query()
ctx.QueryArgs().VisitAll(func(key, value []byte) {
reqQuery.Add(string(key), string(value))
})
requestURIStr := string(requestURI)
parsedURI.RawQuery = reqQuery.Encode()
log.Println("getting", requestURIStr)
uriStr := parsedURI.String()
log.Println("getting", uriStr)
req.SetRequestURI(uriStr)
req.SetRequestURI(requestURIStr)
req.Header.SetUserAgentBytes([]byte("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36"))
resp := fasthttp.AcquireResponse()
@ -216,7 +206,7 @@ func (p *Proxy) RequestHandler(ctx *fasthttp.RequestCtx) {
}
}
}
error_message := fmt.Sprintf("invalid response: %d", resp.StatusCode())
error_message := fmt.Sprintf("invalid response: %d (%s)", resp.StatusCode(), requestURIStr)
p.serveMainPage(ctx, resp.StatusCode(), errors.New(error_message))
return
}
@ -239,17 +229,13 @@ func (p *Proxy) RequestHandler(ctx *fasthttp.RequestCtx) {
var responseBody []byte
if len(contentInfo) == 2 && bytes.Contains(contentInfo[0], []byte("text")) {
e, ename, _ := charset.DetermineEncoding(resp.Body(), string(contentType))
if (e != encoding.Nop) && (!strings.EqualFold("utf-8", ename)) {
responseBody, err = e.NewDecoder().Bytes(resp.Body())
if err != nil {
// HTTP status code 503 : Service Unavailable
p.serveMainPage(ctx, 503, err)
return
}
} else {
responseBody = resp.Body()
if len(contentInfo) == 2 && bytes.Contains(contentInfo[1], []byte("ISO-8859-2")) && bytes.Contains(contentInfo[0], []byte("text")) {
var err error
responseBody, err = charmap.ISO8859_2.NewDecoder().Bytes(resp.Body())
if err != nil {
// HTTP status code 503 : Service Unavailable
p.serveMainPage(ctx, 503, err)
return
}
} else {
responseBody = resp.Body()
@ -332,6 +318,7 @@ func sanitizeHTML(rc *RequestConfig, out io.Writer, htmlDoc []byte) {
unsafeElements := make([][]byte, 0, 8)
state := STATE_DEFAULT
for {
token := decoder.Next()
if token == html.ErrorToken {
@ -359,11 +346,12 @@ func sanitizeHTML(rc *RequestConfig, out io.Writer, htmlDoc []byte) {
if bytes.Equal(tag, []byte("base")) {
for {
attrName, attrValue, moreAttr := decoder.TagAttr()
if bytes.Equal(attrName, []byte("href")) {
parsedURI, err := url.Parse(string(attrValue))
if err == nil {
rc.BaseURL = parsedURI
}
if !bytes.Equal(attrName, []byte("href")) {
continue
}
parsedURI, err := url.Parse(string(attrValue))
if err == nil {
rc.BaseURL = parsedURI
}
if !moreAttr {
break
@ -394,15 +382,14 @@ func sanitizeHTML(rc *RequestConfig, out io.Writer, htmlDoc []byte) {
break
}
if bytes.Equal(tag, []byte("meta")) {
sanitizeMetaTag(rc, out, attrs)
break
}
fmt.Fprintf(out, "<%s", tag)
if hasAttrs {
sanitizeAttrs(rc, out, attrs)
if bytes.Equal(tag, []byte("meta")) {
sanitizeMetaAttrs(rc, out, attrs)
} else {
sanitizeAttrs(rc, out, attrs)
}
}
if token == html.SelfClosingTagToken {
@ -414,10 +401,6 @@ func sanitizeHTML(rc *RequestConfig, out io.Writer, htmlDoc []byte) {
}
}
if bytes.Equal(tag, []byte("head")) {
fmt.Fprintf(out, HTML_META_CONTENT_TYPE)
}
if bytes.Equal(tag, []byte("form")) {
var formURL *url.URL
for _, attr := range attrs {
@ -515,7 +498,7 @@ func sanitizeLinkTag(rc *RequestConfig, out io.Writer, attrs [][][]byte) {
}
}
func sanitizeMetaTag(rc *RequestConfig, out io.Writer, attrs [][][]byte) {
func sanitizeMetaAttrs(rc *RequestConfig, out io.Writer, attrs [][][]byte) {
var http_equiv []byte
var content []byte
@ -528,17 +511,8 @@ func sanitizeMetaTag(rc *RequestConfig, out io.Writer, attrs [][][]byte) {
if bytes.Equal(attrName, []byte("content")) {
content = attrValue
}
if bytes.Equal(attrName, []byte("charset")) {
// exclude <meta charset="...">
return
}
}
if bytes.Equal(http_equiv, []byte("content-type")) {
return
}
out.Write([]byte("<meta"))
urlIndex := bytes.Index(bytes.ToLower(content), []byte("url="))
if bytes.Equal(http_equiv, []byte("refresh")) && urlIndex != -1 {
contentUrl := content[urlIndex+4:]
@ -555,7 +529,7 @@ func sanitizeMetaTag(rc *RequestConfig, out io.Writer, attrs [][][]byte) {
} else {
sanitizeAttrs(rc, out, attrs)
}
out.Write([]byte(">"))
}
func sanitizeAttrs(rc *RequestConfig, out io.Writer, attrs [][][]byte) {
@ -612,6 +586,7 @@ func (rc *RequestConfig) ProxifyURI(uri string) (string, error) {
if rc.Key == nil {
return fmt.Sprintf("./?mortyurl=%s", url.QueryEscape(uri)), nil
}
return fmt.Sprintf("./?mortyhash=%s&mortyurl=%s", hash(uri, rc.Key), url.QueryEscape(uri)), nil
}