github.com/vugu/vugu@v0.3.6-0.20240430171613-3f6f402e014b/devutil/static.go (about)

     1  package devutil
     2  
     3  import (
     4  	"net/http"
     5  	"os"
     6  	"strings"
     7  	"time"
     8  )
     9  
    10  // DefaultIndex is the default index.html content for a development Vugu app.
    11  // The exact text `<title>Vugu App</title>`, `<!-- styles -->` and `<!-- scripts -->`
    12  // are meant to be replaced as needed if you quickly need to hack in CSS or
    13  // JS references for a development Vugu application.  If you need more control
    14  // than that, just copy it into your application.
    15  var DefaultIndex = StaticContent(`<!doctype html>
    16  <html>
    17  <head>
    18  <title>Vugu App</title>
    19  <meta charset="utf-8"/>
    20  <!-- styles -->
    21  </head>
    22  <body>
    23  <div id="vugu_mount_point">
    24  <img style="position: absolute; top: 50%; left: 50%;" src="https://cdnjs.cloudflare.com/ajax/libs/galleriffic/2.0.1/css/loader.gif">
    25  </div>
    26  <script src="https://cdn.jsdelivr.net/npm/text-encoding@0.7.0/lib/encoding.min.js"></script> <!-- MS Edge polyfill -->
    27  <script src="/wasm_exec.js"></script>
    28  <!-- scripts -->
    29  <script>
    30  var wasmSupported = (typeof WebAssembly === "object");
    31  if (wasmSupported) {
    32  	if (!WebAssembly.instantiateStreaming) { // polyfill
    33  		WebAssembly.instantiateStreaming = async (resp, importObject) => {
    34  			const source = await (await resp).arrayBuffer();
    35  			return await WebAssembly.instantiate(source, importObject);
    36  		};
    37  	}
    38  	var mainWasmReq = fetch("/main.wasm").then(function(res) {
    39  		if (res.ok) {
    40  			const go = new Go();
    41  			WebAssembly.instantiateStreaming(res, go.importObject).then((result) => {
    42  				go.run(result.instance);
    43  			});		
    44  		} else {
    45  			res.text().then(function(txt) {
    46  				var el = document.getElementById("vugu_mount_point");
    47  				el.style = 'font-family: monospace; background: black; color: red; padding: 10px';
    48  				el.innerText = txt;
    49  			})
    50  		}
    51  	})
    52  } else {
    53  	document.getElementById("vugu_mount_point").innerHTML = 'This application requires WebAssembly support.  Please upgrade your browser.';
    54  }
    55  </script>
    56  </body>
    57  </html>
    58  `)
    59  
    60  // DefaultAutoReloadIndex is like DefaultIndex but also includes a script tag to load
    61  // auto-reload.js from the default URL.
    62  var DefaultAutoReloadIndex = DefaultIndex.Replace(
    63  	"<!-- scripts -->",
    64  	"<script src=\"http://localhost:8324/auto-reload.js\"></script>\n<!-- scripts -->")
    65  
    66  var startupTime = time.Now()
    67  
    68  // StaticContent implements http.Handler and serves the HTML content in this string.
    69  type StaticContent string
    70  
    71  // ServeHTTP implements http.Handler
    72  func (sc StaticContent) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    73  	http.ServeContent(w, r, r.URL.Path, startupTime, strings.NewReader(string(sc)))
    74  }
    75  
    76  // Replace performs a single string replacement on this StaticContent and returns the new value.
    77  func (sc StaticContent) Replace(old, new string) StaticContent {
    78  	return StaticContent(strings.Replace(string(sc), old, new, 1))
    79  }
    80  
    81  // StaticFilePath implements http.Handler and serves the file at this path.
    82  type StaticFilePath string
    83  
    84  // ServeHTTP implements http.Handler
    85  func (sfp StaticFilePath) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    86  	f, err := os.Open(string(sfp))
    87  	if err != nil {
    88  		msg, code := toHTTPError(err)
    89  		http.Error(w, msg, code)
    90  		return
    91  	}
    92  	defer f.Close()
    93  	st, err := f.Stat()
    94  	if err != nil {
    95  		msg, code := toHTTPError(err)
    96  		http.Error(w, msg, code)
    97  		return
    98  	}
    99  	http.ServeContent(w, r, r.URL.Path, st.ModTime(), f)
   100  }