Guide to Building and Implementing Responses in Empress for Developers

Introduction

In the development of Empress applications, the build_response function plays a pivotal role, allowing you to construct responses depending on the type of content. This guide delves into the technical implementation of the build_response function and discusses how to use it in your Empress scripts and apps.

An Overview of build_response

build_response is a critical feature in Empress, where it is used to build responses based on content type. It’s part of the frappe.utils.response module and is crucial for routing and response handling.

Here’s how build_response is currently implemented:

def build_response(response_type=None):
  if "docs" in frappe.local.response and not frappe.local.response.docs:
    del frappe.local.response["docs"]

  response_type_map = {
    "csv": as_csv,
    "txt": as_txt,
    "download": as_raw,
    "json": as_json,
    "pdf": as_pdf,
    "page": as_page,
    "redirect": redirect,
    "binary": as_binary,
  }

  return response_type_map[frappe.response.get("type") or response_type]()

The build_response function uses a dictionary, response_type_map, to map different response types to corresponding handler functions.

Deep Dive into the “download” response_type

Consider the response handler for the “download” response_type:

def as_raw():
  response = Response()
  response.mimetype = (
    frappe.response.get("content_type")
    or mimetypes.guess_type(frappe.response["filename"])[0]
    or "application/unknown"
  )
  response.headers["Content-Disposition"] = (
    f'{frappe.response.get("display_content_as", "attachment")};'
    f' filename="{frappe.response["filename"].replace(" ", "_")}"'
  ).encode("utf-8")
  response.data = frappe.response["filecontent"]
  return response

The browser’s behavior when receiving the response may vary depending on the Content-Disposition header’s value. If unset, the value defaults to “attachment”. If frappe.response.display_content_as is set to “inline”, the content is expected to be displayed inline in the browser, as a part of a webpage. If set to “attachment”, the content is to be downloaded and saved locally.

Crafting an API Endpoint for File Download

To create an API endpoint that downloads a file, you could use the following code:

@frappe.whitelist()
def download(name):
  file = frappe.get_doc("File", name)
  frappe.response.filename = file.file_name
  frappe.response.filecontent = file.get_content()
  frappe.response.type = "download"
  frappe.response.display_content_as = "attachment"

This function will trigger a download of the specified file when the API endpoint is accessed.

Conclusion

The build_response feature in Empress serves as a powerful tool for developers, enabling them to customize responses based on content types efficiently. It’s an essential asset when building business solutions, facilitating streamlined communication between the server and the client, and significantly enhancing the user experience.