github.com/vchain-us/vcn@v0.9.11-0.20210921212052-a2484d23c0b3/pkg/cmd/serve/serve.go (about)

     1  /*
     2   * Copyright (c) 2018-2020 vChain, Inc. All Rights Reserved.
     3   * This software is released under GPL3.
     4   * The full license information can be found under:
     5   * https://www.gnu.org/licenses/gpl-3.0.en.html
     6   *
     7   */
     8  
     9  package serve
    10  
    11  import (
    12  	"fmt"
    13  	"github.com/spf13/viper"
    14  	"net/http"
    15  
    16  	"github.com/gorilla/handlers"
    17  	"github.com/gorilla/mux"
    18  	"github.com/spf13/cobra"
    19  	"github.com/vchain-us/vcn/internal/logs"
    20  	"github.com/vchain-us/vcn/pkg/meta"
    21  )
    22  
    23  // NewCommand returns the cobra command for `vcn serve`
    24  func NewCommand() *cobra.Command {
    25  	cmd := &cobra.Command{
    26  		Use:   "serve",
    27  		Short: "Start a local API server",
    28  		Long: `Start a local API server
    29  
    30  In Codenotary Cloud mode api key is required. Provide it using x-notarization-lc-api-key header on each request.
    31  
    32  Environment variables:
    33  VCN_USER=
    34  VCN_PASSWORD=
    35  VCN_NOTARIZATION_PASSWORD=
    36  VCN_NOTARIZATION_PASSWORD_EMPTY=
    37  VCN_OTP=
    38  VCN_OTP_EMPTY=
    39  VCN_LC_HOST=
    40  VCN_LC_PORT=
    41  VCN_LC_CERT=
    42  VCN_LC_SKIP_TLS_VERIFY=false
    43  VCN_LC_NO_TLS=false
    44  `,
    45  		PreRunE: func(cmd *cobra.Command, args []string) error {
    46  			return viper.BindPFlags(cmd.Flags())
    47  		},
    48  		RunE: func(cmd *cobra.Command, args []string) error {
    49  			cmd.SilenceUsage = true
    50  			return runServe(cmd)
    51  		},
    52  		Args: cobra.NoArgs,
    53  	}
    54  	cmd.Flags().String("host", "", "host address")
    55  	cmd.Flags().String("port", "8080", "port")
    56  	cmd.Flags().String("tls-cert-file", "", "TLS certificate file")
    57  	cmd.Flags().String("tls-key-file", "", "TLS key file")
    58  
    59  	cmd.Flags().String("lc-host", "", meta.VcnLcHostFlagDesc)
    60  	cmd.Flags().String("lc-port", "443", meta.VcnLcPortFlagDesc)
    61  	cmd.Flags().String("lc-cert", "", meta.VcnLcCertPathDesc)
    62  	cmd.Flags().Bool("lc-skip-tls-verify", false, meta.VcnLcSkipTlsVerifyDesc)
    63  	cmd.Flags().Bool("lc-no-tls", false, meta.VcnLcNoTlsDesc)
    64  
    65  	return cmd
    66  }
    67  
    68  func runServe(cmd *cobra.Command) error {
    69  
    70  	host, err := cmd.Flags().GetString("host")
    71  	if err != nil {
    72  		return nil
    73  	}
    74  	port, err := cmd.Flags().GetString("port")
    75  	if err != nil {
    76  		return nil
    77  	}
    78  	addr := host + ":" + port
    79  
    80  	certFile, _ := cmd.Flags().GetString("tls-cert-file")
    81  	keyFile, _ := cmd.Flags().GetString("tls-key-file")
    82  	if certFile != "" && keyFile == "" {
    83  		return fmt.Errorf("--tls-key-file is missing")
    84  	}
    85  	if certFile == "" && keyFile != "" {
    86  		return fmt.Errorf("--tls-cert-file is missing")
    87  	}
    88  
    89  	lcHost := viper.GetString("lc-host")
    90  	lcPort := viper.GetString("lc-port")
    91  	lcCert := viper.GetString("lc-cert")
    92  	skipTlsVerify := viper.GetBool("lc-skip-tls-verify")
    93  	noTls := viper.GetBool("lc-no-tls")
    94  
    95  	sh := handler{
    96  		lcHost:          lcHost,
    97  		lcPort:          lcPort,
    98  		lcCert:          lcCert,
    99  		lcSkipTlsVerify: skipTlsVerify,
   100  		lcNoTls:         noTls,
   101  	}
   102  
   103  	router := mux.NewRouter().StrictSlash(true)
   104  	router.HandleFunc("/", index)
   105  	router.HandleFunc("/notarize", sh.signHandler(meta.StatusTrusted)).Methods("POST")
   106  	router.HandleFunc("/untrust", sh.signHandler(meta.StatusUntrusted)).Methods("POST")
   107  	router.HandleFunc("/unsupport", sh.signHandler(meta.StatusUnsupported)).Methods("POST")
   108  	router.HandleFunc("/authenticate/{hash}", sh.verify).Methods("GET")
   109  	router.HandleFunc("/inspect/{hash}", sh.inspectHandler).Methods("GET")
   110  
   111  	logs.LOG.Infof("Log level: %s", logs.LOG.GetLevel().String())
   112  	logs.LOG.Infof("Stage: %s", meta.StageEnvironment().String())
   113  
   114  	handler := handlers.CORS(
   115  		handlers.AllowedOrigins([]string{"*"}),
   116  		handlers.AllowedMethods([]string{"POST", "GET", "OPTIONS"}),
   117  		handlers.AllowedHeaders([]string{"content-type", "authorization", "x-notarization-password", "x-notarization-password-empty"}),
   118  	)(router)
   119  
   120  	if certFile != "" && keyFile != "" {
   121  		logs.LOG.Infof("Listening on %s (TLS)", addr)
   122  		return http.ListenAndServeTLS(addr, certFile, keyFile, handler)
   123  	}
   124  
   125  	logs.LOG.Infof("Listening on %s", addr)
   126  	return http.ListenAndServe(addr, handler)
   127  }
   128  
   129  func index(w http.ResponseWriter, r *http.Request) {
   130  	// can be used for healthcheck
   131  	writeResponse(w, http.StatusOK, []byte("OK"))
   132  }