Response

Response Data

The Response from the handler function is passed to the template to be converted to HTML. The handler response is accessible through .Data, or $Data if in another scope. Any python object can be used as the return value. Using a dictionary is recommended, so that error handling is easier. Adding a Error key in the response dict can indicate to the template that an error condition needs to be handled.

For example, a handler like

app.star
def handler(req):
    name = req.Query.get("name")

    if name:
        return {"Name": name[0], "Error": None}
    else:
        return {"Error": "Name not specified", "Name": None}

app = ace.app("test", routes = [ace.html("/")])

allows the template to handle the error by doing

{{block "clace_body" .}}
{{if .Data.Error}}
    <div style="color: red">{{.Data.Error}}</div>
{{else}}
    Hi {{.Data.Name}}
{{end}}
{{end}}

Redirect Response

If the API needs to redirect the client to another location after a POST/PUT/DELETE operation, the handler function can return an ace.Redirect structure. The fields in this structure are:

PropertyOptionalTypeDefaultNotes
urlfalsestringThe url to redirect to
codetrueint303The HTTP status code, 303 or 302

For example, this code does a 303 redirect after a POST API, which provides handling for update requests.

app.star
def create_game(req):
    level = req.Form["level"]
    ret = http.post(SERVICE_URL + "/api/create_game/" + level[0])
    return ace.redirect(req.AppPath + "/game/" + ret.json()["GameId"])

Custom Response

In some cases, a custom response need to be generated, with special headers. Or the response needs to use a template different from the one defined in the route, which could happen in the case of an error. For such cases, a ace.Response structure can be returned by the handler. The fields in this structure are:

PropertyOptionalTypeDefaultNotes
datafalseobjectThe response data
blocktruestringOptional only if type is “json”
typetruestringinherited from the route type definitionIf “json”, block is ignored
codetrueint200HTTP status code
retargettruestringHX-Retarget header value, CSS selector to target, like “#error_id”
reswaptruestringHX-Reswap, like “outerHTML”

For example, this handler code uses retarget to handle errors by updating the html property which has id “gameErrorId”

app.star
ret = http.post(api_url).json()
if ret.get("Error"):
    return ace.response(ret, "game_error_block", retarget="#gameErrorId")
return fetch_game(req, game_id)

This code returns a 404 with a custom body generated from a template block called “invalid_challenge_block”

app.star
if challenge.get("Error"):
    return ace.response(challenge, "invalid_challenge_block", code=404)

JSON Response

All responses are HTML by default, as required for building a proper Hypermedia client. There are some cases where data needs to be returned to the client in JSON format. The type property can be used for those cases. For example, this API returns JSON

app.star
ace.api("/memory", handler=memory_handler),

Here, the response from the handler function is returned as JSON, no template is used. Also, in this handler, if there is a call to ace.Response, the type will default to JSON since that is the type specified at the route level. Mime type detection based on the Accept header is planned, it is not currently supported.