const failable get()

in modules/server/mod-eval.hpp [695:779]


const failable<int> get(const list<value>& rpath, request_rec* const r, const lvvlambda& impl) {
    debug(r->uri, "modeval::get::uri");

    // Inspect the query string
    const list<value> args = httpd::unescapeArgs(httpd::queryArgs(r));
    const list<value> ia = assoc(value("id"), args);
    const list<value> ma = assoc(value("method"), args);

    // Evaluate a JSON-RPC request and return a JSON result
    if (!isNull(ia) && !isNull(ma)) {

        // Extract the request id, method and params
        const value id = cadr(ia);
        const value func = c_str(json::funcName(string(cadr(ma))));

        // Apply the requested function
        const failable<value> val = failableResult(impl(cons(func, json::queryParams(args))));
        if (!hasContent(val))
            return mkfailure<int>(val);

        // Return JSON result
        return httpd::writeResult(json::jsonResult(id, content(val)), "application/json-rpc; charset=utf-8", r);
    }

    // Evaluate the GET expression
    const list<value> params(append<value>(cddr(rpath), mkvalues(args)));
    const failable<value> val = failableResult(impl(cons<value>("get", mklist<value>(params))));
    if (!hasContent(val))
        return mkfailure<int>(val);
    const value c = content(val);
    debug(c, "modeval::get::content");

    // Return a nil value as a not found status
    if (!isList(c) && isNull(c))
        return HTTP_NOT_FOUND;

    // Write in the format requested by the client, if any
    const list<value> fmt = assoc<value>("format", args);
    const value mtype = !isNull(fmt)? cadr(fmt) : acceptMediaType(r);
    if (!isNull(mtype)) {
        if (mtype == "scheme")
            return httpd::writeResult(scheme::writeValue(c), "text/x-scheme; charset=utf-8", r);
        if (mtype == "json")
            return httpd::writeResult(json::writeValue(c), "application/json; charset=utf-8", r);
        if (mtype == "xml")
            return httpd::writeResult(xml::writeElements(valuesToElements(c)), "text/xml; charset=utf-8", r);
    }

    // Write a simple value as a JSON value
    if (!isList(c)) {
        debug(c, "modeval::get::value");
        return httpd::writeResult(json::writeValue(c), "application/json; charset=utf-8", r);
    }

    // Write an empty list as a JSON value
    if (isNull((list<value>)c)) {
        debug(nilListValue, "modeval::get::empty");
        return httpd::writeResult(json::writeValue(c), "application/json; charset=utf-8", r);
    }

    // Write content-type / content-list pair
    if (isString(car<value>(c)) && !isNull(cdr<value>(c)) && isList(cadr<value>(c)))
        return httpd::writeResult(convertValues<string>(cadr<value>(c)), car<value>(c), r);

    // Write an assoc value as a JSON value
    if (isSymbol(car<value>(c)) && !isNull(cdr<value>(c))) {
        debug(c, "modeval::get::assoc");
        return httpd::writeResult(json::writeValue(c), "application/json; charset=utf-8", r);
    }

    // Write an ATOM feed or entry
    const list<value> e = valuesToElements(c);
    if (isList(car<value>(e)) && !isNull(car<value>(e))) {
        const list<value> el = car<value>(e);
        if (isSymbol(car<value>(el)) && car<value>(el) == element && !isNull(cdr<value>(el)) && isSymbol(cadr<value>(el)) && elementHasChildren(el) && !elementHasValue(el)) {
            if (cadr<value>(el) == atom::feed)
                return httpd::writeResult(atom::writeATOMFeed(e), "application/atom+xml; charset=utf-8", r);
            if (cadr<value>(el) == atom::entry)
                return httpd::writeResult(atom::writeATOMEntry(e), "application/atom+xml; charset=utf-8", r);
        }
    }

    // Write any other compound value as a JSON value
    return httpd::writeResult(json::writeValue(c), "application/json; charset=utf-8", r);
}