valum-framework / valum

Web micro-framework written in Vala
https://valum-framework.readthedocs.io/en/latest/
GNU Lesser General Public License v3.0
227 stars 23 forks source link

[question] Subclassed Router missing context variable #217

Closed greenmanspirit closed 7 years ago

greenmanspirit commented 7 years ago

Hello, I am trying to subclass Router but when I try to access my context variable, it is not there. With the code below, I am accessing it with 0.0.0.0:3000/board/1 and the view method is called.

using Json;
using Json.Api;
using Mysql;
using Valum;
using VSGI;

public class Kanban.BoardRouter : Router {
    private unowned Database database;

        public BoardRouter(Database d) {
            this.database = d;
            rule (Method.GET, "/board/<int:id>", view);
            //rule (Method.GET | Method.POST, "/admin/user/<int:id>", edit);
        }

        public bool view (Request req, Response res) {
            Board board = new Board(this.database);
            stdout.printf("context %s\n", context.contains("id").to_string());
            //board.find_by_id(int.parse(context["id"].get_string()));
            return send_response(res, "board", board);
        }

        private bool send_response(Response res, string type, GLib.Object? object) {
            var payload = new ResourcePayload(new Json.Api.Resource("0", type, Json.gobject_serialize(object).dup_object()));
            size_t length;
            res.headers.set_content_type("Application/vnd.json+api", new HashTable<string, string>(str_hash, str_equal));
            try {
                return res.expand_utf8(Json.gobject_to_data(payload, out length));
            } catch(GLib.IOError e) {
                error("%s", e.message);
            }
        }

        /*public bool edit (Request req, Response res) {
            var user = User.find (ctx["id"]);
            if (req.method == "POST") {
                user.values (Soup.Form.decode (req.flatten_utf8 ()));
                user.update ();
            }
            return render_template ("user", user);
        }*/

}
greenmanspirit commented 7 years ago

I added question to the title because I don't see how to add a question label.

elegaanz commented 7 years ago

I think you need to define your view method like that:

public bool view (Request req, Response, res, NextCallback next, Context context) {
    // Do whatever you want with context here
}

Because context is not a property of the Router class, but a parameter passed to your handlers.

arteymix commented 7 years ago

Bat41 is correct here, your function definition is lacking the full signature. If you don't specify the handler-specific context, it will default to the global routing context which is in the lexical scope.

I'd suggest at this point to put the route bindings in a construct {} block such that it can let you define alternate constructors as well.

Unrelated, but I'll probably implement a builder for JSON-Api-GLIb to write payloads as expression similar to what Compose allows.

Happy hacking!

greenmanspirit commented 7 years ago

That fixed it! I based this off of the example here, http://docs.valum-framework.org/en/latest/router/#cleaning-up-route-logic.

Thanks! I am enjoying this and JSON-Api-GLib. I am working on a Kanban server to learn Meson, Vala, Valum and JSON-Api-GLib.

arteymix commented 7 years ago

Try to stick on the 0.3.* series. I'm trying to introduce a more class-based API to enable more introspection and Vala-friendly patterns in the next release.

I think this question can be marked as addressed.