github.com/thetreep/go-swagger@v0.0.0-20240223100711-35af64f14f01/docs/faq/faq_server.md (about)

     1  <!-- Questions about server generation -->
     2  ## Server generation and customization
     3  
     4  ### What are the dependencies required by the generated server?
     5  The code generation process ends with a message indicating package dependencies for your generated code.
     6  
     7  Basically, here are the required packages:
     8  - [`github.com/go-openapi/errors`](https://www.github.com/go-openapi/errors)
     9  - [`github.com/go-openapi/loads`](https://www.github.com/go-openapi/loads)
    10  - [`github.com/go-openapi/runtime`](https://www.github.com/go-openapi/runtime)
    11  - [`github.com/go-openapi/spec`](https://www.github.com/go-openapi/spec)
    12  - [`github.com/go-openapi/strfmt`](https://www.github.com/go-openapi/strfmt)
    13  - [`github.com/go-openapi/swag`](https://www.github.com/go-openapi/swag)
    14  - [`github.com/go-openapi/validate`](https://www.github.com/go-openapi/validate)
    15  
    16  And depending on your generation options, a command line flags handling package:
    17  - [`github.com/jessevdk/go-flags`](https://www.github.com/jessevdk/go-flags), or
    18  - [`github.com/spf13/pflag`](https://www.github.com/spf13/pflag)
    19  - [`flag`](flag)
    20  
    21  This dependency used to be necessary up to release 0.14:
    22  - [`github.com/tylerb/graceful`](https://www.github.com/tylerb/graceful)
    23  
    24  These packages may of course be *vendored* with your own source.
    25  
    26  Originally from issue [#1085](https://github.com/thetreep/go-swagger/issues/1085).
    27  
    28  ### How to add custom flags?
    29  `go-swagger` ships with an option to select a flag management package: `swagger generate server --flag-strategy=[go-flags|pflag|flag]`
    30  
    31  You may of course customize your server to accept arbitrary flags the way you prefer.
    32  This should be normally done with the generated main.go. For customization, you may either skip the generation of the main package (`--skip-main`)
    33  and provide your own, or customize template generation to generate a custom main.
    34  
    35  Here's an example: [kv store example](https://github.com/go-openapi/kvstore/blob/master/cmd/kvstored/main.go#L50-L57)
    36  
    37  Originally from issue [#1036](https://github.com/thetreep/go-swagger/issues/1036).
    38  
    39  ### How do you integrate the flag sets of go-swagger and other packages, in particular, glog?
    40  _Use-case_: logger
    41  >I am trying to integrate a package into a go-swagger generated API that is using the `github.com/golang/glog` logger.
    42  >When I initialize the glog logger it appears to shield the flags defined in the go-swagger runtime.
    43  
    44  **Answer**: the generated API has a Logger property that is a function with signature: `func(string, ...interface{})`
    45  
    46  You can configure it with any logger that exposes the signature.
    47  
    48  eg.: https://github.com/thetreep/go-swagger/blob/master/examples/authentication/restapi/configure_auth_sample.go#L33
    49  
    50  _Use-case_: logger flags
    51  >Still having a problem with how and where to initialize glog so that both sets of flags are honored:
    52  >the runtime flags, such as `--tls-certificate` and the glog flags like `-log_dir` and `-stderrthreshold`.
    53  
    54  >If I initialize glog in the config_xxx.go I don't get the go-swagger runtime flags, and if I initialize glog in the engine, I get the error: `logging before flag.Parse`.
    55  >I realize that this question is not so much about logging *per se*, but more about how to merge the flag sets defined by different packages.
    56  
    57  **Answer**: you can generate a server with `--flag-strategy pflag`
    58  
    59  After that you can use its integration to add goflags. You would do this in the main file.
    60  Subsequently it's probably a good idea to generate code with `--exclude-main` so the update is preserved.
    61  
    62  See also: https://github.com/spf13/pflag#supporting-go-flags-when-using-pflag
    63  
    64  Example:
    65  ```golang
    66  import (
    67      goflag "flag"
    68      flag "github.com/spf13/pflag"
    69  )
    70  
    71  var ip *int = flag.Int("flagname", 1234, "help message for flagname")
    72  
    73  func main() {
    74      flag.CommandLine.AddGoFlagSet(goflag.CommandLine)
    75      flag.Parse()
    76  }
    77  ```
    78  
    79  Originally from issue [#762](https://github.com/thetreep/go-swagger/issues/762).
    80  
    81  ### How to serve two or more swagger specs from one server?
    82  _Use-case_: I want a go-swagger generated server to serve 2 swagger specs that have no overlap on paths.
    83  One is a generic metadata api that is implemented by many services and the other is a
    84  service-specific api. The built-in server.go template Server struct, by having exactly
    85  one API & handler, appears to prevent this.
    86  
    87  **Suggestions**:
    88  1. Use go-swagger `mixin` command to merge specs into a single one
    89  2. Create yourself a top-level swagger file that just includes the two lower-level ones (using `$ref`).
    90  You may use go-swagger `flatten` to flatten the resulting spec
    91  3. You can also make your own main function and use the code from the generation
    92  of both spec (with `--skip-main`).
    93  This allows for customization like using a different middleware stack, which in turn gives you
    94  the ability to serve 2 swagger specs at different paths.
    95  
    96  Originally from issue [#1005](https://github.com/thetreep/go-swagger/issues/1005). *(comes with a sample main.go for spec composition)*.
    97  
    98  ### How to access access API struct inside operator handler?
    99  _Use-Case_:
   100  my question is how can I access the generated API interface from within an operation handler function ?
   101  Can i pass it somehow via context or any other way to do that?
   102  
   103  **Answer**: **No**. It's not reachable from within the handler anywhere.
   104  
   105  
   106  >I created a module like apache access module ACL based on IP address for different URLs.
   107  >Instead of URL for lookup key I decided to use Operation.ID.
   108  >Lookup would be faster in that way because each operation has a unique id according to swagger specification.
   109  >The problem comes when I want to check against that ACL of mine...
   110  
   111  **Suggestions**:
   112  This is possible in 2 ways.
   113  - first way is by using an authenticator,
   114  - the second way is making a middleware (not global)
   115  
   116  Example with Authenticator:
   117  ```golang
   118  // Authenticator represents an authentication strategy
   119  // implementations of Authenticator know how to authenticate the
   120  // request data and translate that into a valid principal object or an error
   121  type Authenticator interface {
   122      Authenticate(interface{}) (bool, interface{}, error)
   123  }
   124  ```
   125  You may see the schemes currently supported here: https://github.com/go-openapi/runtime/tree/master/security
   126  
   127  Example with Middleware:
   128  ```golang
   129  // The middleware configuration is for the handler executors. These do not apply to the swagger.json document.
   130  // The middleware executes after routing but before authentication, binding and validation.
   131  func setupMiddlewares(handler http.Handler) http.Handler {
   132      return handler
   133  }
   134  ```
   135  to get to the matched route in one of those you can:
   136  ```golang
   137  import "github.com/gorilla/context"
   138  context.Get(3, request)
   139  ```
   140  That gets you a matched route.
   141  
   142  >Note: it might be worth it to expose `Context` as an exported method on the API builder.
   143  >That would be a simple PR to add the following code in go-swagger
   144  ```golang
   145  func (o *LifecycleManagerAPI) Context() *middleware.Context {
   146      if o.context == nil {
   147          o.context = middleware.NewRoutableContext(o.spec, o, nil)
   148      }
   149      return o.context
   150  }
   151  ```
   152  then your middleware could take a context in and use `RouteInfo(request)` like this one: https://github.com/go-openapi/runtime/blob/master/middleware/security.go.
   153  
   154  _Similar use-case_:
   155  I have some domain objects I need access to in the handlers (db connection, telemetry client, etc).
   156  
   157  *What is the recommended way/place to define these and access them in the handlers?*
   158  
   159  >Would I define them in configure_xxx() and make wrapper functions for the handlers to make them accessible?
   160  >Or is there a nice way to add them to the context?
   161  >I was looking for some examples of this but couldn't find anything.
   162  
   163  **Hint**: look at this one: https://github.com/go-openapi/kvstore
   164  
   165  The important takeaway is that main and the handlers have to be pulled outside of the generated code since only configure_xxx() is protected.
   166  And main() doesn't call configureAPI() ...
   167  that was a little confusing looking through the other examples and not seeing any changes to the vanilla config code.
   168  
   169  _Similar use-case_: dependency injection
   170  
   171  Wouldn't it be better to have all the handlers automatically be part of a default struct that simply has a Context member variable or empty interface?
   172  
   173  >That would save everyone a lot of copy/paste when we need to inject some info.
   174  >I mean, a different context than the one available on params.HTTPRequest.Context(),
   175  >more like an application level context, e.g. something I can stuff a database reference or other business state into.
   176  
   177  **Hint**: remember that the generated packages are made of a series of files that you can extend and tailor to your own needs by adding more files.
   178  
   179  For instance, a new (non generated) file in the operations package could bring to life the applicative context/dependencies injection and be called from the configure_xxx.
   180  You may alternatively modify the generation by providing your own templates, and possibly extend the interface of the Server struct.
   181  
   182  Originally from issue [#661](https://github.com/thetreep/go-swagger/issues/661).
   183  
   184  ### Use go-swagger to generate different client or servers
   185  _Use-Case_:
   186  I am using go-swagger to generate some part of a server application automatically
   187  and I would love to reuse our code by transforming the code in go templates.
   188  
   189  >It would be  enough to export the `appGenerator` type and have a function that returns it (maybe generator.GenerateServer itself?).
   190  >I would then use `appGenerator` to execute the templates.
   191  >How could I realize this? Is it possible with go-swagger?
   192  
   193  **Answer**: you can provide your own templates for go-swagger.
   194  
   195  The client and server generators allow you to specify a directory on disk to add custom templates.
   196  
   197  Here are some docs: http://goswagger.io/generate/templates/
   198  
   199  >In VIC they do this: https://github.com/vmware/vic/tree/master/lib/apiservers/templates
   200  >https://github.com/vmware/vic/blob/master/Makefile#L274-L281
   201  
   202  **Hint**: you can also override templates by using the same names:
   203  https://github.com/thetreep/go-swagger/blob/master/generator/templates.go#L61-L73
   204  
   205  *Wouldn't this generate roughly the same structure of the server?*
   206  
   207  >I don't want to change minor details, I want to have code that looks totally different
   208  >(but only for the server part, models and clients are more than okay) while using code the parsing and validation from go-swagger.
   209  >This means different number of files and different functionalities.
   210  
   211  **Answer**: yes, it would generate a similar structure.
   212  
   213  Note: customizing templates already brings many options to the table, including generating artifacts in other languages than go.
   214  
   215  There is some documentation on the config file format here: https://github.com/thetreep/go-swagger/blob/gen-layout-configfile/docs/use/template_layout.md
   216  
   217  Also keep in mind that `go-openapi` and `go-swagger` constitute a _toolkit_
   218  and provide you the *tools* to adapt to your own use case.
   219  The `swagger` command line and standard templates only covers general purpose use-cases.
   220  
   221  If you think your use-case would benefit to many people, feel free to make the necessary changes for your case to work and submitting a PR.
   222  
   223  Example config file for generation:
   224  ```YAML
   225  layout:
   226    application:
   227      - name: configure
   228        source: asset:serverConfigureapi
   229        target: "{{ joinFilePath .Target .ServerPackage }}"
   230        file_name: "{{ .Name }}_client.go"
   231        skip_exists: true
   232      - name: main
   233        source: asset:serverMain
   234        target: "{{ joinFilePath .Target \"cmd\" (dasherize (pascalize .Name)) }}-server"
   235        file_name: "main.go"
   236      - name: embedded_spec
   237        source: asset:swaggerJsonEmbed
   238        target: "{{ joinFilePath .Target .ServerPackage }}"
   239        file_name: "embedded_spec.go"
   240      - name: server
   241        source: asset:serverServer
   242        target: "{{ joinFilePath .Target .ServerPackage }}"
   243        file_name: "server.go"
   244      - name: builder
   245        source: asset:serverBuilder
   246        target: "{{ joinFilePath .Target .ServerPackage .Package }}"
   247        file_name: "{{ snakize (pascalize .Name) }}_api.go"
   248      - name: doc
   249        source: asset:serverDoc
   250        target: "{{ joinFilePath .Target .ServerPackage }}"
   251        file_name: "doc.go"
   252    models:
   253     - name: definition
   254       source: asset:model
   255       target: "{{ joinFilePath .Target .ModelPackage }}"
   256       file_name: "{{ (snakize (pascalize .Name)) }}.go"
   257    operations:
   258     - name: parameters
   259       source: asset:serverParameter
   260       target: "{{ joinFilePath .Target .ServerPackage .APIPackage .Package }}"
   261       file_name: "{{ (snakize (pascalize .Name)) }}_parameters.go"
   262     - name: responses
   263       source: asset:serverResponses
   264       target: "{{ joinFilePath .Target .ServerPackage .APIPackage .Package }}"
   265       file_name: "{{ (snakize (pascalize .Name)) }}_responses.go"
   266     - name: handler
   267       source: asset:serverOperation
   268       target: "{{ joinFilePath .Target .ServerPackage .APIPackage .Package }}"
   269       file_name: "{{ (snakize (pascalize .Name)) }}.go"
   270  ```
   271  
   272  ### Support streaming responses
   273  _Use-Case_: Docker client expects a stream of JSON structs from daemon to show a progress bar, as in:
   274  ```bash
   275  curl -i -X POST http://IP:PORT/images/create?fromImage=alpine&tag=latest
   276  ```
   277  *How could I write a server providing a streaming response?*
   278  
   279  **Answer**: Operations in the generated server are expected to return a responder.
   280  
   281  This interface is defined as:
   282  ```golang
   283  // Responder is an interface for types to implement
   284  // when they want to be considered for writing HTTP responses
   285  type Responder interface {
   286      WriteResponse(http.ResponseWriter, httpkit.Producer)
   287  }
   288  ```
   289  
   290  With the `middleware.ResponderFunc` helper construct, you can just write a `func(http.ResponseWriter, httpkit.Producer)`
   291  where you want a streaming response.
   292  
   293  This should be sufficient. However:
   294  
   295  >I've toyed with a channel based stream where you send struct objects to a channel, which then gets streamed to the browser.
   296  >I decided against this because it seemed to just add complexity for little benefit.
   297  >I can be persuaded to implement such a responder though, and should somebody send a PR like that I would not say no to it.
   298  
   299  Originally from issue [#305](https://github.com/thetreep/go-swagger/issues/305).
   300  
   301  ### OAuth authentication does not redirect to the authorization server
   302  _Use-Case_: oauth2 accessCode flow does not redirect to the authorization server
   303  
   304  > In my understanding, if the accessCode flow is used for oauth2 securitydefinition, the generated server could redirect the authentication to the oauth2 server, e.g., https://accounts.google.com/o/oauth2/v2/auth. However, my generated code does not perform the redirection. Could anyone help on this? Thanks.
   305  
   306  Like in:
   307  ```yaml
   308  ---
   309  swagger: '2.0'
   310  info:
   311    title: oauth2 debug
   312    version: 0.3.0
   313  produces:
   314  - application/json
   315  schemes:
   316    - http
   317  basePath: /api
   318  securityDefinitions:
   319    OauthSecurity:
   320      type: oauth2
   321      flow: accessCode
   322      authorizationUrl: 'https://accounts.google.com/o/oauth2/v2/auth'
   323      tokenUrl: 'hhttps://www.googleapis.com/oauth2/v4/token'
   324      scopes:
   325        admin: Admin scope
   326        user: User scope
   327  security:
   328    - OauthSecurity:
   329      - user
   330  paths:
   331    /customers:
   332    ....
   333  ```
   334  
   335  
   336  > The generated server does not redirect the browser to the google login page.
   337  
   338  **Answer**: Redirection flow is for UI. The spec has them so your UI can do the redirection.
   339  
   340  Swagger 2.0 only defines those properties as hints for a UI to work,
   341  this doesn't have to be server side. At the same time the redirection flow is not supported in an API
   342  but you can use an OAuth 2.0 middleware from any library to get you that functionality
   343  
   344  Originally from issue [#1217](https://github.com/thetreep/go-swagger/issues/1217).
   345  
   346  ### HTTPS TLS Cipher Suites not supported by AWS Elastic LoadBalancer
   347  
   348  _Use-case_: AWS Elastic LoadBalancer forwards https requests to instances, and their security policy is 'ELBSecurityPolicy-2016-08'.
   349  However, while running the server on https, the server keeps on logging
   350  
   351  `http: TLS handshake error from 192.168.X.X:XXXXX: tls: no cipher suite supported by both client and server.`
   352  
   353  If we remove the cipher suites on the generated code, it resolves the issue -
   354  
   355  ```golang
   356  CipherSuites: []uint16{
   357    tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
   358    tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
   359    tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
   360    tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
   361  },
   362  ```
   363  
   364  The ELB security policy 'ELBSecurityPolicy-2016-08' does include these cipher suites, however all requests sent by the ELB are rejected by the server.
   365  
   366  **Answer**: you can generate the server with a different compatibility mode for the older generation of ciphers
   367  
   368  ```
   369  swagger generate server --compatibility-mode=intermediate
   370  ```
   371  
   372  Originally from issue [#1383](https://github.com/thetreep/go-swagger/issues/1383).
   373  
   374  ### Which mime types are supported?
   375  
   376  _Use-Case_: I seem to be unable to find supported mime-types that the API's can consume and produce. Any references?
   377  
   378  **Answer**: see the current list of supported media MIMEs [here](https://github.com/thetreep/go-swagger/blob/3099f611ada66d42974160ac4e0ec475d24b7041/generator/support.go#L279)
   379  You can add more through the consumer producer mechanism.
   380  
   381  Originally from issue [#1022](https://github.com/thetreep/go-swagger/issues/1022).
   382  
   383  ### Is it possible to return error to main function of server?
   384  
   385  _Use-Case_: Is it possible to return error to main function of server?
   386  
   387  > For example, my server saves some configs in file, and I want that if config file is missing,
   388  > then server must be stopped with some error code. It is possible to do it with panic(err),
   389  > but I think it is not good way. So can I return error main function of server ?
   390  
   391  **Answer**: you can make your own main function.
   392  
   393  There is an example here: https://github.com/go-openapi/kvstore/blob/master/cmd/kvstored/main.go
   394  
   395  There is a command line argument to avoid overwriting the main when generating: `--exclude-main`.
   396  
   397  Originally from issue [#1060](https://github.com/thetreep/go-swagger/issues/1060).
   398  
   399  -------------
   400  
   401  Back to [all contributions](README.md#all-contributed-questions)