-1

Right now, I can only view a PlainTextResponse by manually entering the API URL path into my browser. However, I would like to be able to view PlainTextResponses in my Swagger UI. It seems like the OpenAPI loads indefinitely every time I try to request a PlainTextResponse

Here is a sample:

from fastapi import FastAPI
from fastapi.responses import PlainTextResponse
import pandas as pd

app = FastAPI()

@app.get("/plain_text", response_class=PlainTextResponse)
async def plain_text():
    url = 'https://raw.githubusercontent.com/ccodwg/Covid19Canada/master/official_datasets/can/phac_n_tests_performed_timeseries_prov.csv'
    df = pd.read_csv(url, index_col=0)
    return PlainTextResponse(df.to_csv(index=False), media_type="text/plain")

This sample actually works. I'm assuming its because this specific CSV file is relatively small.

However, once you start using larger CSV files, it seems like you are unable to display the response in the UI. For example, try https://raw.githubusercontent.com/Schlumberger/hackathon/master/backend/dataset/data-large.csv instead and it will load forever on the UI but displays relatively quickly if you use the URL path.

  • It's very hard for anyone to say anything useful without you including a proper example that shows the issue - otherwise we'll just have to make guesses about what could be the cause of the problem. Create a minimum, verifiable example that illustrates the behavior and what you want to happen instead. – MatsLindh Jul 04 '22 at 19:25
  • @MatsLindh just added a sample. – bravesheeptribe Jul 04 '22 at 20:43

2 Answers2

0

I don't know what is happening in at your end, but here is a mvp showing how PlainTextRepsonse comes through in the auto generated docs.

from fastapi import FastAPI
from fastapi.responses import PlainTextResponse

app = FastAPI()


@app.get("/")
def root():
    return PlainTextResponse("Plain Response!")


if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000,  )

Executing the operation (using the "Try out" button) in the generated docs, yields the following result:

enter image description here

JarroVGIT
  • 4,291
  • 1
  • 17
  • 29
  • I just added my own mvp. It seems to work with very simple and small responses, but once they start getting large the UI seems to just break. – bravesheeptribe Jul 04 '22 at 20:41
  • You are not trying to send a PlainTextResponse, but a full CSV file. Although it should work, it is clearly not meant for that and I don't think you can blame an automated frontend for not accommodating such a use case. Try a file response, or a StreamResponse, but not a PlainTextResponse. – JarroVGIT Jul 04 '22 at 20:48
  • I'm using PlainTextResponse so it returns something similar to raw.githubusercontent.com rather than download the file to the user's computer. I'm assuming that FastAPI just has a size limit for what can be displayed in the UI then. – bravesheeptribe Jul 04 '22 at 20:59
  • If you want a raw response such as Github, then my previous comment is even more prudent. You are using the wrong Response type. `PlainTextResponse` is not made for large bodies of text. – JarroVGIT Jul 05 '22 at 04:52
  • Thank you for your advice. I have changed it, and it seems like disabling syntax highlighting in SwaggerUI solves the issue. – bravesheeptribe Jul 05 '22 at 16:09
0

Turns out, it's not PlainTextResponse's issue but rather SwaggerUI, credits to this user's answer. Disabling syntax highlighting seems to significantly improve performance and hence the Swagger UI no longer hangs on large responses.

from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import pandas as pd

app = FastAPI(swagger_ui_parameters={"syntaxHighlight": False})

@app.get("/plain_text", response_class=StreamingResponse)
async def plain_text():
    url = 'https://raw.githubusercontent.com/Schlumberger/hackathon/master/backend/dataset/data-large.csv'
    df = pd.read_csv(url, index_col=0)
    return StreamingResponse(iter([df.to_csv(index=False)]), media_type="text/csv")