Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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

Is there a way to hide some fields from OpenAPI specs? #1708

Closed
9 tasks done
mclate opened this issue Jul 13, 2020 · 14 comments
Closed
9 tasks done

Is there a way to hide some fields from OpenAPI specs? #1708

mclate opened this issue Jul 13, 2020 · 14 comments

Comments

@mclate
Copy link

mclate commented Jul 13, 2020

First check

  • I added a very descriptive title to this issue.
  • I used the GitHub search to find a similar issue and didn't find it.
  • I searched the FastAPI documentation, with the integrated search.
  • I already searched in Google "How to X in FastAPI" and didn't find any information.
  • I already read and followed all the tutorial in the docs and didn't find an answer.
  • I already checked if it is not related to FastAPI but to Pydantic.
  • I already checked if it is not related to FastAPI but to Swagger UI.
  • I already checked if it is not related to FastAPI but to ReDoc.
  • After submitting this, I commit to one of:
    • Read open issues with questions until I find 2 issues where I can help someone and add a comment to help there.
    • I already hit the "watch" button in this repository to receive notifications and I commit to help at least 2 people that ask questions in the future.
    • Implement a Pull Request for a confirmed bug.

Example

Here's a self-contained, minimal, reproducible, example with my use case:

from fastapi import FastAPI

app = FastAPI()


@app.get("/")
def read_root(hidden_param=Query(None, description="This parameter should not be visible in OpenApi specs")):
    if hidden_param:
        return {"Hello": "Master!"}
    else:
        return {"Hello": "World"}

Description

I'd like to have some request parameters (query or body ones) to be available in the python code, but to be hidden from the OpenAPI specs. Wonder if it is possible to do?

@mclate mclate added the question Question or problem label Jul 13, 2020
@tiangolo
Copy link
Owner

Hmm, interesting...

I guess we could have a parameter include_in_schema for Query, Body, etc, something like:

from fastapi import FastAPI, Query, Body
from pydantic import BaseModel

app = FastAPI()


@app.get("/")
def read_root(hidden_param: str = Query(None, include_in_schema=False)):
    if hidden_param:
        return {"Hello": "Master!"}
    else:
        return {"Hello": "World"}


class Item(BaseModel):
    name: str
    price: float


@app.post("/items/")
def create_item(item: Item = Body(None, include_in_schema=False)):
    return item

BTW, if you want to selectively remove or alter things from the schema for a Pydantic model you can already do that with schema_extra: https://pydantic-docs.helpmanual.io/usage/schema/#schema-customization

@roeeyn
Copy link

roeeyn commented Jul 24, 2020

Cool @tiangolo, I will give it a try 😄

@itssimon
Copy link
Contributor

itssimon commented Oct 8, 2020

I would also be interested in an include_in_schema argument for Query, Body etc.

@Gatux
Copy link

Gatux commented Oct 12, 2020

It may also be useful with Header to hide x-forwarded-for from the documentation for example, when FastAPI is used behind a reverse proxy.

@mnorrsken
Copy link

I would like this feature too. We have a header with auth info thats always sent from our API manager to our backend. I want to consume this header in my API but I don't want it to show up in the docs.

@dvarrazzo
Copy link

dvarrazzo commented Nov 28, 2020

Another use case: testing. In order to test the expiry of a session I use an header parameter and pass a short timeout to test for session expiry:

async def login(auth: AuthForm, x_session_timeout_sec: Optional[float] = Header(None)) -> LoginResponse:
    kw = {}
    conf = get_config()
    if conf.testing:
        kw["timeout_sec"] = x_session_timeout_sec

    await create_session(user_data, **kw)
    ...

the use of such parameter can be disabled in production, testing it against env vars, but it's not easy to change the signature of the python function based on env vars, and changing the openapi.json for every such use is pretty cumbersome.

@mnorrsken
Copy link

I have got around it by using a Depends which looks at the request directly so its not showing the parameter in documentation.

@daniel-demelo
Copy link

daniel-demelo commented Apr 14, 2021

@mnorrsken how did you get rid of the parameters with Depends?
The function that I have inside Depends requires a parameter and so it is also appearing in the docs :/
Here's an example:

@router.get("/health")
async def health_check(*, settings = Depends(config.get_settings)) -> dict:
    """Answers ok if the system is up and running."""

    # settings = config.get_settings()

    return {
        "Application": settings.app_name,
        "Status": "OK",
    }

#config.py
def get_settings(env_file: str = None):
    #...

To solve that I moved I moved the settings declaration to inside the function, which solved the problem.
At first I thought that nothing from Depends would get shown in the docs, but I was wrong, it does show.
Then, wondering if it was possible to hide fields from the OpenAPI brought me here :)

@mnorrsken
Copy link

Sorry for late reply. Im using the raw request object in the parameters and extracting my data from that. it would becomes something like
def get_settings(req: Request): return req.query_params[’env_file’]

@joeriddles
Copy link

I am also running into the same issue mentioned by @daniel-demelo. In my case, I have a service listed as a dependency for a router. The service has an Optional argument that defaults to None. This is to allow easier testing using DI.

router.py

router = APIRouter()

@router.get("/")
def get(service=Depends(Service):
  ...

service.py

class Service():
  def __init__(self, thing: Optional[SomeNonPydanticThing]=None):
    self.thing = thing or SomeNonPydanticThing() # use passed in value if truthy, else create a default value

I am getting the following error:

fastapi.exceptions.FastAPIError: Invalid args for response field! Hint: check that typing.Optional[some.module.SomeNonPydanticThing] is a valid pydantic field type

Perhaps Depends could have a new parameter, include_in_schema, like the way fields are hidden from the OpenAPI spec in #3012.

@jossefaz
Copy link

jossefaz commented Nov 15, 2021

Agree with @joeriddles : include_in_schema for Depends too would be wonderful

@nbraun-wolf
Copy link

I have got around it by using a Depends which looks at the request directly so its not showing the parameter in documentation.

unless you want to use the result of depends in your handler.

@tiangolo
Copy link
Owner

Thanks, everyone! This was included in #3144, it's now available in FastAPI version 0.73.0 🎉

@github-actions
Copy link
Contributor

github-actions bot commented Feb 3, 2022

Assuming the original need was handled, this will be automatically closed now. But feel free to add more comments or create new issues or PRs.

@github-actions github-actions bot closed this as completed Feb 3, 2022
@tiangolo tiangolo reopened this Feb 28, 2023
Repository owner locked and limited conversation to collaborators Feb 28, 2023
@tiangolo tiangolo converted this issue into discussion #7341 Feb 28, 2023

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Projects
None yet
Development

No branches or pull requests