Skip to content

Commit

Permalink
Add basic setup for serving a MUD via HTTP
Browse files Browse the repository at this point in the history
  • Loading branch information
hslatman committed Jul 29, 2021
1 parent ef7ce66 commit f30e49e
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 5 deletions.
63 changes: 58 additions & 5 deletions cmd/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,76 @@ limitations under the License.
package cmd

import (
"fmt"
"log"
"net/http"
"time"

"github.com/hslatman/mud-cli/internal"
"github.com/hslatman/mud-cli/web"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)

// viewCmd represents the view command
var viewCmd = &cobra.Command{
Use: "view",
Short: "Provides a graphical view of a MUD file",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("view called")
// TODO: check if file exists locally or download temp copy
// TODO: serve the file locally; temporarily
Args: cobra.MinimumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {

filepath := args[0]
mudfile, err := internal.ReadMUDFileFrom(filepath)
if err != nil {
return errors.Wrap(err, "could not get contents")
}

json, err := internal.JSON(mudfile)
if err != nil {
return errors.Wrap(err, "getting JSON representation of MUD file failed")
}

// TODO: open browser; show MUD Visualizer with the chosen MUD file
// TODO: provide option to show it in terminal?

mudHandler := newMUDHandler(json)

// Strip / and prepend build, so that a file `a/b.js` would be
// found in web/build/a/b.js, but served from localhost:8080/a/b.js.
webHandler := web.AssetHandler("/", "build")

mux := http.NewServeMux()
mux.Handle("/mud", mudHandler)
mux.Handle("/", webHandler)
mux.Handle("/*filepath", webHandler)

s := &http.Server{
Addr: ":8080",
Handler: mux,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}

log.Fatal(s.ListenAndServe()) // TODO: add some logging?

return nil
},
}

type mudHandler struct {
json string
}

func (m *mudHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(m.json))
}

func newMUDHandler(json string) http.Handler {
return &mudHandler{
json: json,
}
}

func init() {
rootCmd.AddCommand(viewCmd)
}
1 change: 1 addition & 0 deletions internal/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ func Read(filepath string) ([]byte, error) {
// TODO: provide additional parameters for filetype to retrieve (or use a MUD client abstraction?)
// so that the right headers can be provided in the requests (and check these in the response?)
// TODO: RFC states that MUD URL should be HTTPS; fail on that here if not?
// TODO: get rid of the temp file? I think it's relatively safe to keep the content bytes in memory
f, err := ioutil.TempFile(os.TempDir(), "")
if err != nil {
return []byte{}, err
Expand Down
43 changes: 43 additions & 0 deletions web/build.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// web/build.go
package web

import (
"embed"
"io/fs"
"net/http"
"os"
"path"
)

//go:embed build/*
var Assets embed.FS

// fsFunc is short-hand for constructing a http.FileSystem
// implementation
type fsFunc func(name string) (fs.File, error)

func (f fsFunc) Open(name string) (fs.File, error) {
return f(name)
}

// AssetHandler returns an http.Handler that will serve files from
// the Assets embed.FS. When locating a file, it will strip the given
// prefix from the request and prepend the root to the filesystem
// lookup: typical prefix might be /web/, and root would be build.
func AssetHandler(prefix, root string) http.Handler {
handler := fsFunc(func(name string) (fs.File, error) {
assetPath := path.Join(root, name)

// If we can't find the asset, return the default index.html content
f, err := Assets.Open(assetPath)
if os.IsNotExist(err) {
return Assets.Open("build/index.html")
}

// Otherwise assume this is a legitimate request routed
// correctly
return f, err
})

return http.StripPrefix(prefix, http.FileServer(http.FS(handler)))
}
9 changes: 9 additions & 0 deletions web/build/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Test</title>
</head>
<body>
Testing ...
</body>
</html>

0 comments on commit f30e49e

Please sign in to comment.