ogen-go / ogen

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

CORS headers: The only allowed header is Content-Type #1320

Open Russia9 opened 1 month ago

Russia9 commented 1 month ago

What version of ogen are you using?

$ go list -m github.com/ogen-go/ogen
github.com/ogen-go/ogen v1.4.1

Can this issue be reproduced with the latest version?

Yes

What did you do?

I created an OpenAPI spec that utilizes a custom user-defined header and has a Bearer security scheme:

openapi: 3.1.0
info:
  title: Simple API
  description: A simple API with header utilization
  version: 1.0.0
paths:
  /items:
    get:
      summary: Retrieve a list of items
      security:
        - bearerAuth: []
      parameters:
        - name: X-Custom-Header
          in: header
          required: true
          description: Custom header for request
          schema:
            type: string
      responses:
        "200":
          description: A list of items
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

Then I called an OPTIONS request to the /items path.

What did you expect to see?

There are headers Authorization, X-Custom-Header and Content-Type in the Access-Control-Allow-Headers header of the OPTIONS response for /items

What did you see instead?

The only CORS-allowed header is Content-Type image

Probable cause

It seems like the Access-Control-Allow-Headers is hardcoded in the template gen/_template/cfg.tmpl:

...
MethodNotAllowed: func(w http.ResponseWriter, r *http.Request, allowed string) {
            status := http.StatusMethodNotAllowed
            if r.Method == "OPTIONS" {
                w.Header().Set("Access-Control-Allow-Methods", allowed)
                w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
                status = http.StatusNoContent
            } else {
                w.Header().Set("Allow", allowed)
            }
            w.WriteHeader(status)
        },
...

It can currently be mitigated by either setting this header in the reverse proxy or redefining the MethodNotAllowed function using ServerOptions.

I propose an addition to the signature of this function to include not only allowed methods but also allowed headers.

tdakkota commented 1 month ago

You can override default handler via WithMethodNotAllowed option. https://github.com/ogen-go/ogen/blob/4182357878201caf52384c2acd887b44d02a3a1f/gen/_template/cfg.tmpl#L258-L265