1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
|
package sockjs
import (
"fmt"
"io"
"net/http"
"regexp"
"strings"
)
var iframeTemplate = `<!doctype html>
<html><head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head><body><h2>Don't panic!</h2>
<script>
document.domain = document.domain;
var c = parent.%s;
c.start();
function p(d) {c.message(d);};
window.onload = function() {c.stop();};
</script>
`
var invalidCallback = regexp.MustCompile(`[^a-zA-Z0-9_.]`)
func init() {
iframeTemplate += strings.Repeat(" ", 1024-len(iframeTemplate)+14)
iframeTemplate += "\r\n\r\n"
}
func (h *Handler) htmlFile(rw http.ResponseWriter, req *http.Request) {
rw.Header().Set("content-type", "text/html; charset=UTF-8")
if err := req.ParseForm(); err != nil {
http.Error(rw, err.Error(), http.StatusBadRequest)
return
}
callback := req.Form.Get("c")
if callback == "" {
http.Error(rw, `"callback" parameter required`, http.StatusBadRequest)
return
} else if invalidCallback.MatchString(callback) {
http.Error(rw, `invalid character in "callback" parameter`, http.StatusBadRequest)
return
}
rw.WriteHeader(http.StatusOK)
fmt.Fprintf(rw, iframeTemplate, callback)
rw.(http.Flusher).Flush()
sess, err := h.sessionByRequest(req)
if err != nil {
http.Error(rw, err.Error(), http.StatusInternalServerError)
return
}
recv := newHTTPReceiver(rw, req, h.options.ResponseLimit, new(htmlfileFrameWriter), ReceiverTypeHtmlFile)
if err := sess.attachReceiver(recv); err != nil {
if err := recv.sendFrame(cFrame); err != nil {
http.Error(rw, err.Error(), http.StatusInternalServerError)
return
}
recv.close()
return
}
sess.startHandlerOnce.Do(func() { go h.handlerFunc(Session{sess}) })
select {
case <-recv.doneNotify():
case <-recv.interruptedNotify():
}
}
type htmlfileFrameWriter struct{}
func (*htmlfileFrameWriter) write(w io.Writer, frame string) (int, error) {
return fmt.Fprintf(w, "<script>\np(%s);\n</script>\r\n", quote(frame))
}
|