API Route Response
In this chapter, you'll learn how to send a response in your API route.
Send a JSON Response#
To send a JSON response, use the JSON method of the MedusaResponse object that is passed as the second parameter of your API route handler.
For example:
func customGET(req *medusahttp.MedusaRequest, res *medusahttp.MedusaResponse) error {
return res.JSON(map[string]any{
"message": "Hello, World!",
})
}
This API route returns the following JSON object:
The JSON method accepts any value that Go's encoding/json package can marshal, such as maps, structs with json tags, and slices. It returns an error if the value can't be marshaled, so return it from the handler.
Set Response Status Code#
By default, setting the JSON data using the JSON method returns a response with a 200 status code.
To change the status code, use the Status method of the MedusaResponse object before you send the response. It returns the response, so you can chain it with the JSON method.
For example:
func customPOST(req *medusahttp.MedusaRequest, res *medusahttp.MedusaResponse) error {
return res.Status(201).JSON(map[string]any{
"message": "Created!",
})
}
The response of this API route has the status code 201.
Change Response Content Type#
To return response data other than a JSON object, set the response headers with the SetHeader method of the MedusaResponse object, which includes the content type. Then, send the response with the Send method, which accepts a string.
Send sets the Content-Type header to text/html; charset=utf-8 if you haven't set it.Example: Return a File#
To create an API route that returns a PDF file, you can set the Content-Type header to application/pdf:
func invoiceFile(req *medusahttp.MedusaRequest, res *medusahttp.MedusaResponse) error {
// assuming you have the file's content as a byte slice
content := []byte("%PDF-1.4 ...")
res.SetHeader("Content-Type", "application/pdf")
res.SetHeader("Content-Disposition", `attachment; filename="invoice.pdf"`)
res.Send(string(content))
return nil
}
Example: Return XML Content#
To create an API route that returns XML content, you can set the Content-Type header to application/xml:
func reportXML(req *medusahttp.MedusaRequest, res *medusahttp.MedusaResponse) error {
res.SetHeader("Content-Type", "application/xml; charset=utf-8")
res.Send(`<?xml version="1.0" encoding="UTF-8"?><report><status>ok</status></report>`)
return nil
}
Example: Server-Sent Events (SSE)#
To create an API route that returns server-sent events (SSE), set the Content-Type header to text/event-stream, then call the Writer method. It sends the status code and headers, and returns the underlying http.ResponseWriter that you can write the stream to.
func streamGET(req *medusahttp.MedusaRequest, res *medusahttp.MedusaResponse) error {
res.SetHeader("Content-Type", "text/event-stream")
res.SetHeader("Cache-Control", "no-cache")
res.SetHeader("Connection", "keep-alive")
res.Status(200)
// Writer sends the status and headers, then gives access to the
// underlying writer.
w := res.Writer()
flusher, _ := w.(nethttp.Flusher)
if flusher != nil {
flusher.Flush()
}
ticker := time.NewTicker(3 * time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
_, _ = w.Write([]byte("data: Streaming data...\n\n"))
if flusher != nil {
flusher.Flush()
}
case <-req.Request.Context().Done():
// the client closed the connection
return nil
}
}
}
This API route opens a stream by setting the Content-Type to text/event-stream. It then simulates a stream with a ticker that writes the stream data every three seconds, and flushes it to the client.
The handler returns when the client closes the connection, which you detect with the Done channel of the request's context. Use req.Request.Context() for that, instead of req.Ctx(), which isn't canceled when the client disconnects.
Other Response Methods#
These are the other methods of MedusaResponse that you can use:
Method | Description |
|---|---|
| Returns the response's |
| Sets the status code and sends the status's text as the body. |
| Ends the response without a body, with the status set by |
| Returns the underlying |
| Registers a function to run once the response is sent. |
JSON and Send compute a weak ETag header for the response, and answer a GET or HEAD request that has a matching If-None-Match header with a 304 status code, like the API routes of Medusa do.