csv response для swagger 2.0 & codegen (golang)

Пишу хэндлер, который в ответ присылает csv файл. На проекте используем swagger 2.0 в формате json и по нему codegen. Так вот есть несколько проблем:

  1. Когда запускаю генерацию кода по спецификации, то codegen генерирует CSVProducer так:
CsvProducer: runtime.ProducerFunc(func(w io.Writer, data interface{}) error {
            return errors.NotImplemented("csv producer has not yet been implemented")
        }),

При этом JsonProducer и JsonConsumer генерируются правильно, с функциями из пакета runtime. Для CSV формата в том же пакете есть свои consumer и producer, но генерирует он почему-то их так, как я представил код выше. Естественно если я руками изменю, то в будущем при очередной генерации все слетает к дефолтному коду в виде возвращения того, что consumer не имплементирован.

  1. Если я все же руками поменяю все как надо и попробую проверить, то у меня при запросе, который должен вернуть csv файл вернется это (тестирую в insomnia):
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: X-API-KEY,X-USER-ID,X-SPLIT-NAME,Content-Type
Access-Control-Allow-Methods: GET,POST,PUT,PATCH,DELETE,OPTIONS
Access-Control-Allow-Origin: *
Content-Type: text/csv
Date: Tue, 14 Mar 2023 10:11:11 GMT
Content-Length: 0

Как видно, Content-Length: 0. При этом в коде возникает ошибка:

2023/03/14 10:11:11 http: superfluous response.WriteHeader call from pkg/api/middleware.LoggingMiddleware.func1.1.1 (middleware.go:122)
2023-03-14T10:11:11.445777085Z goroutine 79 [running]:
2023-03-14T10:11:11.445809960Z runtime/debug.Stack()
...

Вот код функции pkg/api/middleware.LoggingMiddleware:

func LoggingMiddleware(ctx *open_middleware.Context) open_middleware.Builder {
    return func(h http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            defer func() {
                if recov := recover(); recov != nil {
                    w.WriteHeader(http.StatusInternalServerError)
                    debug.PrintStack()
                    log.
                        Error().
                        Interface("err", recov).
                        Msg(r.URL.Path)

                }
            }()

            start := time.Now()
            wrapped := wrapResponseWriter(w)

            // print body
            body := &bytes.Buffer{}
            content, _ := ioutil.ReadAll(r.Body)
            defer r.Body.Close()
            l := len(content)
            if l > bufferLen {
                l = bufferLen
            }
            body.Write(content[:l])
            r.Body = ioutil.NopCloser(bytes.NewReader(content))

            h.ServeHTTP(wrapped, r)

            if wrapped.Status() != http.StatusOK && wrapped.Status() != http.StatusNoContent {
                cLogger := log.Info().
                    Int("status", wrapped.Status()).
                    Str("method", r.Method).
                    Str("path", routePath(r, ctx)).
                    Dur("duration", time.Since(start)).
                    Str("query", r.URL.RawQuery).
                    RawJSON("body", body.Bytes()).
                    Str("user", r.URL.User.String()).
                    Str("api-key", r.Header.Get("X-API-KEY")).
                    Str("user-id", r.Header.Get("X-USER-ID"))

                cLogger.Str("resp", wrapped.body.String())

                cLogger.Msg(r.URL.Path)
            }

        })
    }

}

Вот код хэндлера в swagger 2.0 json:

"/file": {
      "get": {
        "tags": [
          "files"
        ],
        "operationId": "GetCSVFile",
        "parameters": [
          {
            "name": "fileName",
            "in": "query",
            "required": true,
            "type": "string"
          }
        ],
        "produces": [
          "text/csv"
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "schema": {
              "$ref": "#/definitions/GetCSVFileResponse"
            },
            "headers": {
              "Content-Disposition": {
                "type": "string",
                "description": "Attachment; filename=example.csv"
              }
            }
          },
          "default": {
            "$ref": "#/responses/defaultResponse"
          }
        }
      }
    },

    ...

    "GetCSVFileResponse": {
      "type": "string",
      "format": "binary",
      "description": "CSV file response",
      "x-go-mimetype": "text/csv",
      "x-go-fileName": "example.csv",
      "x-nullable": false
    },

Пробовал по разному оформлять файл swagger для правильной генерации, но ни один из вариантов не привел к правильной работе.


Ответы (0 шт):