-
Notifications
You must be signed in to change notification settings - Fork 72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Response schema for []byte is always generated as array of integer rather than byte/binary string #115
Comments
thank for reporting this and providing the example with expected output. I need to look back at the setup to see what is possible now or what can be done to achieve this. |
i am investigating whether adding |
for fields of type
|
Thanks for the details! I was wondering if there was a struct tag-style way to do it. At the moment, I'm literally returning a We did find a workaround using |
As a quick experiment, I tried the previous strategy of using a package main
import (
"crypto/rand"
"log"
"net/http"
restful "github.com/emicklei/go-restful"
restfulspec "github.com/emicklei/go-restful-openapi"
)
type BinaryResponse struct {
bytes []byte `format:"binary"`
}
func getRandomBytes(size int) ([]byte, error) {
b := make([]byte, size)
_, err := rand.Read(b)
if err != nil {
return nil, err
}
return b, nil
}
func WebService() *restful.WebService {
ws := new(restful.WebService)
ws.Path("/").Produces(restful.MIME_OCTET)
ws.Route(ws.GET("/bytes").To(getRandomBytesTest).
Doc("get random bytes").
Writes(BinaryResponse{}).
//Produces(restful.MIME_OCTET).
//Returns(200, "OK", []byte{}))
Returns(200, "OK", BinaryResponse{}))
return ws
}
func getRandomBytesTest(_ *restful.Request, response *restful.Response) {
responseBytes, _ := getRandomBytes(256)
//_, _ = response.Write(responseBytes)
byteResponse := BinaryResponse{bytes: responseBytes}
response.WriteEntity(byteResponse)
}
func main() {
restful.DefaultContainer.Add(WebService())
config := restfulspec.Config{
WebServices: restful.RegisteredWebServices(),
APIPath: "/apidocs.json",
}
restful.DefaultContainer.Add(restfulspec.NewOpenAPIService(config))
log.Printf("Get the API using http://localhost:8080/apidocs.json")
log.Fatal(http.ListenAndServe(":8080", nil))
} The full output Swagger then comes out to something like this: {
"swagger": "2.0",
"paths": {
"/bytes": {
"get": {
"produces": [
"application/octet-stream"
],
"summary": "get random bytes",
"operationId": "getRandomBytesTest",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/main.BinaryResponse"
}
}
}
}
}
},
"definitions": {
"main.BinaryResponse": {
"required": [
"bytes"
],
"properties": {
"bytes": {
"type": "string",
"format": "binary"
}
}
}
}
} So it definitely does do the binary property specification as you said. It's not entirely clear to me that in Swagger this means the response should be expected to be raw bytes versus bytes wrapped in a JSON response (though I am not a Swagger expert by any means). |
As a third example, this is what we're doing right now to fix up the Swagger before publishing using the package main
import (
"crypto/rand"
"log"
"net/http"
"github.com/go-openapi/spec"
restful "github.com/emicklei/go-restful"
restfulspec "github.com/emicklei/go-restful-openapi"
)
const (
testPath = "/bytes"
)
func getRandomBytes(size int) ([]byte, error) {
b := make([]byte, size)
_, err := rand.Read(b)
if err != nil {
return nil, err
}
return b, nil
}
func WebService() *restful.WebService {
ws := new(restful.WebService)
ws.Path("/").Produces(restful.MIME_OCTET)
ws.Route(ws.GET(testPath).To(getRandomBytesTest).
Doc("get random bytes").
Writes([]byte{}).
Produces(restful.MIME_OCTET).
Returns(200, "OK", []byte{}))
return ws
}
func getRandomBytesTest(_ *restful.Request, response *restful.Response) {
responseBytes, _ := getRandomBytes(256)
_, _ = response.Write(responseBytes)
}
func main() {
restful.DefaultContainer.Add(WebService())
config := restfulspec.Config{
WebServices: restful.RegisteredWebServices(),
APIPath: "/apidocs.json",
PostBuildSwaggerObjectHandler: interceptSwagger,
}
restful.DefaultContainer.Add(restfulspec.NewOpenAPIService(config))
log.Printf("Get the API using http://localhost:8080/apidocs.json")
log.Fatal(http.ListenAndServe(":8080", nil))
}
func interceptSwagger(s *spec.Swagger) {
if s.Paths != nil {
bytesPath := s.Paths.Paths[testPath]
getObjRes := bytesPath.Get.Responses
if getObjRes != nil {
okRes := getObjRes.StatusCodeResponses[http.StatusOK]
newSchema := new(spec.Schema)
newSchema.Type = []string{"string"}
newSchema.Format = "binary"
okRes.Schema = newSchema
getObjRes.StatusCodeResponses[http.StatusOK] = okRes
}
}
} And that does produce more of the minimal Swagger we're going for: {
"swagger": "2.0",
"paths": {
"/bytes": {
"get": {
"produces": [
"application/octet-stream"
],
"summary": "get random bytes",
"operationId": "getRandomBytesTest",
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "string",
"format": "binary"
}
}
}
}
}
}
} |
Hello,
I'm currently running into an issue where the Swagger generated for our service definition translates
Writes([]byte{})
to an array of integer in the output Swagger spec. This is causing some issues for downstream code generation where clients are incorrectly attempting to use[]int
rather than[]byte
when forming requests I saw another user mention the same thing in another issue here: #77 (comment)To be very specific, going by https://swagger.io/docs/specification/data-models/data-types/#file, I need a way to make this translate to
"type": "string"
and"format": "binary"
(or"byte"
) in the output Swagger definition. Is there a good way to do that?I adapted one of your previous examples to show what I mean if it helps. I made a really simple API that just returns a random byte array:
When running that application and visiting http://localhost:8080/apidocs.json, it produces the following Swagger:
But what I need is to be able to produce this instead for the response:
Is that something that would be feasible to do with the library? And if so, would you be able to suggest how I might be able to achieve that? Thank you for your time and help!
The text was updated successfully, but these errors were encountered: