2021-03-20 20:40:40 +00:00
// SPDX-FileCopyrightText: 2021 Luke Granger-Brown <depot@lukegb.com>
//
// SPDX-License-Identifier: Apache-2.0
2021-03-20 19:53:43 +00:00
package cmd
import (
"context"
"fmt"
2021-03-21 03:04:38 +00:00
"log"
2021-03-20 19:53:43 +00:00
"net/http"
2021-03-21 18:52:22 +00:00
"os/exec"
2021-03-21 18:04:37 +00:00
"strings"
2021-03-20 19:53:43 +00:00
2021-03-21 03:04:38 +00:00
"github.com/google/safehtml"
2021-03-20 19:53:43 +00:00
"github.com/spf13/cobra"
"hg.lukegb.com/lukegb/depot/web/fup/fuphttp"
"hg.lukegb.com/lukegb/depot/web/fup/fupstatic"
2021-03-21 18:52:22 +00:00
"hg.lukegb.com/lukegb/depot/web/fup/minicheddar"
2021-03-20 19:53:43 +00:00
)
func init ( ) {
rootCmd . AddCommand ( serveCmd )
2021-03-21 18:04:37 +00:00
serveCmd . Flags ( ) . StringVar ( & serveRoot , "root" , "http://localhost:8191/" , "Application root address." )
serveCmd . Flags ( ) . StringVar ( & serveStaticRoot , "static-root" , "/static/" , "Root address from which static assets should be referenced." )
2021-03-20 19:53:43 +00:00
serveCmd . Flags ( ) . StringVarP ( & serveBind , "listen" , "l" , ":8191" , "Bind address for HTTP server." )
2021-03-21 03:04:38 +00:00
serveCmd . Flags ( ) . BoolVar ( & serveDirectOnly , "direct-only" , false , "If set, all file serving will be proxied, even if the backend supports signed URLs." )
2021-03-21 18:52:22 +00:00
serveCmd . Flags ( ) . StringVar ( & serveCheddarPath , "cheddar-path" , "cheddar" , "Path to 'cheddar' binary to use for syntax highlighting. If it cannot be found, syntax highlighting and markdown rendering will be disabled." )
serveCmd . Flags ( ) . StringVar ( & serveCheddarAddr , "cheddar-address" , "" , "If non-empty, will be used instead of attempting to spawn a copy of cheddar." )
2021-03-20 19:53:43 +00:00
}
var (
2021-03-21 18:52:22 +00:00
serveBind string
serveRoot string
serveStaticRoot string
serveDirectOnly bool
serveCheddarPath string
serveCheddarAddr string
2021-03-20 19:53:43 +00:00
serveCmd = & cobra . Command {
Use : "serve" ,
Short : "Serve HTTP" ,
RunE : func ( cmd * cobra . Command , args [ ] string ) error {
2021-03-21 18:04:37 +00:00
if ! strings . HasSuffix ( serveRoot , "/" ) {
return fmt . Errorf ( "--root flag should end in / (value is %q)" , serveRoot )
}
if ! strings . HasSuffix ( serveStaticRoot , "/" ) {
return fmt . Errorf ( "--static-root flag should end in / (value is %q)" , serveStaticRoot )
}
2021-03-20 19:53:43 +00:00
ctx := context . Background ( )
2021-03-21 18:52:22 +00:00
highlighter , err := serveCheddar ( ctx )
if err != nil {
return fmt . Errorf ( "spawning cheddar syntax highlighter: %v" , err )
}
2021-03-20 19:53:43 +00:00
cfg := & fuphttp . Config {
2021-03-21 03:04:38 +00:00
Templates : fupstatic . Templates ,
Static : fupstatic . Static ,
2021-03-21 18:04:37 +00:00
StaticRoot : safehtml . TrustedResourceURLFromFlag ( cmd . Flag ( "static-root" ) . Value ) ,
AppRoot : serveRoot ,
2021-03-21 03:04:38 +00:00
StorageURL : bucketURL ,
RedirectToBlobstore : ! serveDirectOnly ,
2021-03-21 18:52:22 +00:00
Highlighter : highlighter ,
2021-03-20 19:53:43 +00:00
}
a , err := fuphttp . New ( ctx , cfg )
if err != nil {
return fmt . Errorf ( "constructing application: %w" , err )
}
http . Handle ( "/" , a . Handler ( ) )
http . Handle ( "/static/" , http . StripPrefix ( "/static/" , http . FileServer ( http . FS ( fupstatic . Static ) ) ) )
2021-03-21 03:04:38 +00:00
log . Printf ( "Serving on %s" , serveBind )
2021-03-20 19:53:43 +00:00
return http . ListenAndServe ( serveBind , nil )
} ,
}
)
2021-03-21 18:52:22 +00:00
func serveCheddar ( ctx context . Context ) ( * minicheddar . Cheddar , error ) {
if serveCheddarAddr != "" {
return minicheddar . Remote ( serveCheddarAddr ) , nil
}
cpath , err := exec . LookPath ( serveCheddarPath )
if err != nil {
log . Printf ( "couldn't find cheddar at %q; disabling syntax highlighting" , serveCheddarPath )
return nil , nil
}
return minicheddar . Spawn ( ctx , cpath )
}