ogen-go / ogen

OpenAPI v3 code generator for go
https://ogen.dev
Apache License 2.0
1.45k stars 86 forks source link

Client Decode fails on simple object: Unable to decode to nil #1310

Closed veqryn closed 2 months ago

veqryn commented 2 months ago

What version of ogen are you using?

v1.4.0

Can this issue be reproduced with the latest version?

Yes

What did you do?

OpenAPI yaml:

openapi: 3.0.3

info:
  title: Awesome GO API
  version: 1.0.0
  description: Actual example use cases for a curated list of golang api generator libraries

servers:
  - url: http://localhost:8080
    description: dev instance

paths:
  /error:
    get:
      summary: Get an error
      description: Responds with an error
      operationId: get-error
      responses:
        400:
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

components:
  schemas:
    Error:
      description: An API error
      type: object
      properties:
        title:
          description: A short, human-readable summary of the problem type. This value should not change between occurrences of the error.
          example: Bad Request
          type: string
        details:
          description: A human-readable explanation specific to this occurrence of the problem.
          example: Property foo is required but is missing.
          type: string
        properties:
          description: Optional map of properties
          nullable: true
          type: object

Server:

package main

import (
    "context"
    "fmt"
    "net/http"

    api "github.com/veqryn/awesome-go-api/openapiv3/ogen/gen"
)

var _ api.Handler = &App{}

type App struct {
    // server.Unimplemented // Can be used to future proof against new api endpoints
}

func (s *App) GetError(ctx context.Context) (*api.Error, error) {
    respErr := &api.Error{
        Title:   api.NewOptString("Bad Request"),
        Details: api.NewOptString("This is an example error"),
        Properties: api.NewOptErrorProperties(&api.ErrorProperties{}),
    }
    return respErr, nil
}

func main() {
    app := &App{}
    server, err := api.NewServer(app)
    if err != nil {
        panic(err)
    }

    http.ListenAndServe(":8080", server)
}

Client:

package main

import (
    "context"
    "fmt"

    "github.com/davecgh/go-spew/spew"
    api "github.com/veqryn/awesome-go-api/openapiv3/ogen/gen"
)

func main() {
    ctx := context.Background()

    // Create client
    c, err := api.NewClient("http://localhost:8080")
    if err != nil {
        panic(err)
    }

    errorResp, err := c.GetError(ctx)
    if err != nil {
        panic(err)
    }

    spew.Dump(errorResp)
}

Result:

panic: decode response: decode application/json: decode Error: callback: decode field "properties": invalid: unable to decode ErrorProperties to nil

If I manually curl the server, I get this back, which is expected:

$ curl -vv -k -L localhost:8080/error
* Host localhost:8080 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:8080...
* Connected to localhost (::1) port 8080
> GET /error HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 400 Bad Request
< Content-Type: application/json; charset=utf-8
< Date: Tue, 10 Sep 2024 07:35:27 GMT
< Content-Length: 76
<
* Connection #0 to host localhost left intact
{"title":"Bad Request","details":"This is an example error","properties":{}}

What did you expect to see?

Everything work fine.

What did you see instead?

An error returned because ogen or its json dependency is unable to unmarshall an empty json object into a simple golang struct.