1
0
mirror of https://github.com/schollz/cowyo.git synced 2023-08-10 21:13:00 +03:00
cowyo/vendor/github.com/shurcooL/go/openutil/openutil.go
2017-10-03 14:43:55 -04:00

111 lines
3.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package openutil displays Markdown or HTML in a new browser tab.
package openutil
import (
"log"
"net"
"net/http"
"strings"
"time"
"github.com/shurcooL/github_flavored_markdown/gfmstyle"
"github.com/shurcooL/go/gfmutil"
"github.com/shurcooL/go/open"
)
// DisplayMarkdownInBrowser displays given Markdown in a new browser window/tab.
func DisplayMarkdownInBrowser(markdown []byte) {
stopServerChan := make(chan struct{})
handler := func(w http.ResponseWriter, req *http.Request) {
gfmutil.WriteGitHubFlavoredMarkdownViaLocal(w, markdown)
// TODO: A better way to fix: /assets/gfm/gfm.css Failed to load resource: net::ERR_CONNECTION_REFUSED.
// HACK: Give some time for other assets to finish loading.
go func() {
time.Sleep(1 * time.Second)
stopServerChan <- struct{}{}
}()
}
http.HandleFunc("/index", handler)
http.Handle("/assets/gfm/", http.StripPrefix("/assets/gfm", http.FileServer(gfmstyle.Assets))) // Serve the "/assets/gfm/gfm.css" file.
http.Handle("/favicon.ico", http.NotFoundHandler())
// TODO: Aquire a free port similarly to using ioutil.TempFile() for files.
// TODO: Consider using httptest.NewServer.
open.Open("http://localhost:7044/index")
err := httpstoppable۰ListenAndServe("localhost:7044", nil, stopServerChan)
if err != nil {
panic(err)
}
}
// DisplayHTMLInBrowser displays given html page in a new browser window/tab.
// query can be empty, otherwise it should begin with "?" like "?key=value".
func DisplayHTMLInBrowser(mux *http.ServeMux, stopServerChan <-chan struct{}, query string) {
// TODO: Aquire a free port similarly to using ioutil.TempFile() for files.
open.Open("http://localhost:7044/index" + query)
err := httpstoppable۰ListenAndServe("localhost:7044", mux, stopServerChan)
if err != nil {
panic(err)
}
}
// ListenAndServe listens on the TCP network address addr
// and then calls Serve with handler to handle requests
// on incoming connections.
// Accepted connections are configured to enable TCP keep-alives.
// Handler is typically nil, in which case the http.DefaultServeMux is
// used.
//
// When receiving from stop unblocks (because it's closed or a value is sent),
// listener is closed and ListenAndServe returns with nil error.
// Otherise, it always returns a non-nil error.
//
// Deprecated: Go 1.8 added native support for stopping a server in net/http.
// net/http should be used instead. This copied function will be removed soon.
func httpstoppable۰ListenAndServe(addr string, handler http.Handler, stop <-chan struct{}) error {
srv := &http.Server{Addr: addr, Handler: handler}
if addr == "" {
addr = ":http"
}
ln, err := net.Listen("tcp", addr)
if err != nil {
return err
}
go func() {
<-stop
err := ln.Close()
if err != nil {
log.Println("httpstoppable.ListenAndServe: error closing listener:", err)
}
}()
err = srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
switch { // Serve always returns a non-nil error.
case strings.Contains(err.Error(), "use of closed network connection"):
return nil
default:
return err
}
}
// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted
// connections. It's used by ListenAndServe so dead TCP connections
// (e.g. closing laptop mid-download) eventually go away.
type tcpKeepAliveListener struct {
*net.TCPListener
}
func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
tc, err := ln.AcceptTCP()
if err != nil {
return
}
tc.SetKeepAlive(true)
tc.SetKeepAlivePeriod(3 * time.Minute)
return tc, nil
}