Skip to content
Snippets Groups Projects
configureapi.gotmpl 7.75 KiB
Newer Older
// This file is safe to edit. Once it exists it will not be overwritten

{{ if .Copyright -}}// {{ comment .Copyright -}}{{ end }}

Christophe de Vienne's avatar
Christophe de Vienne committed
{{- $noDB := not (not (index .Info.Extensions "x-go-orusapi-no-db") ) }}

package {{ .APIPackage }}

import (
  "context"
  "crypto/tls"
  "io"
  "log"
  "net/http"

  "github.com/go-openapi/errors"
  "github.com/go-openapi/runtime"
  "github.com/go-openapi/runtime/middleware"
  "github.com/go-openapi/runtime/security"
  "orus.io/orus-io/go-orusapi"

  {{ imports .DefaultImports }}
  {{ imports .Imports }}
)

// Callback is a simple function
type Callback func()

// Config holds the things required to configure the API
type Config struct {
	Log zerolog.Logger
Christophe de Vienne's avatar
Christophe de Vienne committed

{{- if not $noDB }}
	DB *sqlx.DB
Christophe de Vienne's avatar
Christophe de Vienne committed
{{- end }}
	Shutdown []Callback
	// Here you can add anything the ConfigureAPI function will need to setup
	// the API
}

{{ with .GenOpts }}
//go:generate swagger generate server --target {{ .TargetPath }} --name {{ .Name }} --spec {{ .SpecPath }}
{{- if .APIPackage }}{{ if ne .APIPackage "operations" }} --api-package {{ .APIPackage }}{{ end }}{{ end }}
{{- if .ModelPackage }}{{ if ne .ModelPackage "models" }} --model-package {{ .ModelPackage }}{{ end }}{{ end }}
{{- if .ServerPackage }}{{ if ne .ServerPackage "restapi"}} --server-package {{ .ServerPackage }}{{ end }}{{ end }}
{{- if .ClientPackage }}{{ if ne .ClientPackage "client" }} --client-package {{ .ClientPackage }}{{ end }}{{ end }}
{{- if .TemplateDir }} --template-dir {{ .TemplateDir }}{{ end }}
{{- range .Operations }} --operation {{ . }}{{ end }}
{{- range .Tags }} --tags {{ . }}{{ end }}
{{- if .Principal }} --principal {{ .Principal }}{{ end }}
{{- if .DefaultScheme }}{{ if ne .DefaultScheme "http" }} --default-scheme {{ .DefaultScheme }}{{ end }}{{ end }}
{{- range .Models }} --model {{ . }}{{ end }}
{{- if or (not .IncludeModel) (not .IncludeValidator) }} --skip-models{{ end }}
{{- if or (not .IncludeHandler) (not .IncludeParameters ) (not .IncludeResponses) }} --skip-operations{{ end }}
{{- if not .IncludeSupport }} --skip-support{{ end }}
{{- if not .IncludeMain }} --exclude-main{{ end }}
{{- if .ExcludeSpec }} --exclude-spec{{ end }}
{{- if .DumpData }} --dump-data{{ end }}
{{- if .StrictResponders }} --strict-responders{{ end }}
{{ end }}

type ConfiguredAPI struct {
	api *{{.Package}}.{{ pascalize .Name }}API
	handler http.Handler
func (capi *ConfiguredAPI) Name() string {
	return "{{ .Name }}"
}

func (capi *ConfiguredAPI) Handler() http.Handler {
	return capi.handler
}

func (capi *ConfiguredAPI) PreServerShutdown() {
}

func (capi *ConfiguredAPI) ServerShutdown() {
	lsize := len(capi.config.Shutdown)
	for i := range capi.config.Shutdown {
		capi.config.Shutdown[lsize-i-1]()
	}
func ConfigureAPI(api *{{.Package}}.{{ pascalize .Name }}API, server *orusapi.Server, config Config) (*ConfiguredAPI, error) {
  // configure the api here
  api.ServeError = errors.ServeError

  if config.BaseURL == "" {
    scheme := "https"
    if len(server.EnabledListeners) != 0 {
      scheme = server.EnabledListeners[0]
    }
    config.BaseURL = fmt.Sprintf("%s://%s:%d",
      scheme, server.Host, server.Port,
    )
  }

  // Set your custom logger if needed. Default one is log.Printf
  // Expected interface func(string, ...interface{})
  //
  // Example:
  // api.Logger = log.Printf

  api.UseSwaggerUI()
  // To continue using redoc as your UI, uncomment the following line
  // api.UseRedoc()

  {{ range .Consumes }}
    {{- if .Implementation }}
  api.{{ pascalize .Name }}Consumer = {{ .Implementation }}
    {{- else }}
  api.{{ pascalize .Name }}Consumer = runtime.ConsumerFunc(func(r io.Reader, target interface{}) error {
    return errors.NotImplemented("{{.Name}} consumer has not yet been implemented")
  })
    {{- end }}
  {{- end }}
  {{ range .Produces }}
    {{- if .Implementation }}
  api.{{ pascalize .Name }}Producer = {{ .Implementation }}
    {{- else }}
  api.{{ pascalize .Name }}Producer = runtime.ProducerFunc(func(w io.Writer, data interface{}) error {
    return errors.NotImplemented("{{.Name}} producer has not yet been implemented")
  })
    {{- end }}
  {{- end}}
  {{ range .SecurityDefinitions }}
    {{- if .IsBasicAuth }}
  // Applies when the Authorization header is set with the Basic scheme
  if api.{{ pascalize .ID }}Auth == nil {
    api.{{ pascalize .ID }}Auth = func(user string, pass string) ({{if not ( eq .Principal "interface{}" )}}*{{ end }}{{.Principal}}, error) {
      return nil, errors.NotImplemented("basic auth  ({{ .ID }}) has not yet been implemented")
    }
  }
    {{- else if .IsAPIKeyAuth }}
  // Applies when the "{{ .Name }}" {{ .Source }} is set
  if api.{{ pascalize .ID }}Auth == nil {
    api.{{ pascalize .ID }}Auth = func(token string) ({{if not ( eq .Principal "interface{}" )}}*{{ end }}{{.Principal}}, error) {
      return nil, errors.NotImplemented("api key auth ({{ .ID }}) {{.Name}} from {{.Source}} param [{{ .Name }}] has not yet been implemented")
    }
  }
    {{- else if .IsOAuth2 }}
  if api.{{ pascalize .ID }}Auth == nil {
    api.{{ pascalize .ID }}Auth = func(token string, scopes []string) ({{if not ( eq .Principal "interface{}" )}}*{{ end }}{{.Principal}}, error) {
      return nil, errors.NotImplemented("oauth2 bearer auth ({{ .ID }}) has not yet been implemented")
    }
  }
    {{- end }}
  {{- end }}
  {{- if .SecurityDefinitions }}

  // Set your custom authorizer if needed. Default one is security.Authorized()
  // Expected interface runtime.Authorizer
  //
  // Example:
  // api.APIAuthorizer = security.Authorized()
  {{- end }}
  {{- $package := .Package }}
  {{- range .Operations }}
  if api.{{ if ne .Package $package }}{{ pascalize .Package }}{{ end }}{{ pascalize .Name }}Handler == nil {
    api.{{ if ne .Package $package }}{{pascalize .Package}}{{ end }}{{ pascalize .Name }}Handler =
    {{- .PackageAlias }}.{{- pascalize .Name }}HandlerFunc(func(params {{ .PackageAlias }}.{{- pascalize .Name }}Params
  {{- if $.GenOpts.StrictResponders }}
    {{- if .Authorized}}, principal {{if not ( eq .Principal "interface{}" )}}*{{ end }}{{.Principal}}{{end}}) {{.Package}}.{{ pascalize .Name }}Responder {
     return {{.Package}}.{{ pascalize .Name }}NotImplemented()
  {{ else }}
    {{- if .Authorized}}, principal {{if not ( eq .Principal "interface{}" )}}*{{ end }}{{.Principal}}{{end}}) middleware.Responder {
      return middleware.NotImplemented("operation {{ .Package}}.{{pascalize .Name}} has not yet been implemented")
  {{ end -}}
    })
  }
  {{- end }}
  	if server.Prometheus {
		api.PrometheusInstrumentHandlers()
	}
	api.LoggingInstrumentHandlers()
	return &ConfiguredAPI{
		api: api,
		handler: setupGlobalMiddleware(api.Serve(setupMiddlewares)),
}

// The TLS configuration before HTTPS server starts.
//func configureTLS(tlsConfig *tls.Config) {
  // Make all necessary changes to the TLS configuration here.

// As soon as server is initialized but not run yet, this function will be called.
// If you need to modify a config, store server instance to stop it individually later, this is the place.
// This function can be called multiple times, depending on the number of serving schemes.
// scheme value will be set accordingly: "http", "https" or "unix"
//func configureServer(s *http.Server, scheme, addr string) {
//}

// The middleware configuration is for the handler executors. These do not apply to the swagger.json document.
// The middleware executes after routing but before authentication, binding and validation
func setupMiddlewares(handler http.Handler) http.Handler {
	return handler
}

// The middleware configuration happens before anything, this middleware also applies to serving the swagger.json document.
// So this is a good place to plug in a panic handling middleware, logging and metrics
func setupGlobalMiddleware(handler http.Handler) http.Handler {
	return handler
}