Commit 6014b1c5 authored by Bat's avatar Bat
Browse files

Merge branch 'master' into 'master'

db.all works again and it's easy to manage error pages

Yes, there is two fixes in only one MR…

See merge request !13
parents 70b10573 ef5a3043
Pipeline #9425 passed with stage
in 4 minutes and 3 seconds
......@@ -7,5 +7,5 @@
out/
test/valse.*
serv
.o
*.o
units-tests/tests
using Valse;
using Valse.Default;
public class CustomErrorController : ErrorController {
public override Response error (int code, string message) {
return new Response.from_html ("<h1>:(</h1><p>Something went wrong: %s</p><p>(Error code: %d)</p><h2><a href=\"/\">Go back home</a></h2>".printf (message, code)) {
error_code = code
};
}
}
......@@ -7,7 +7,9 @@ public class HomeController : Controller {
public HomeController () {
this.add_action ("index", this.index);
this.add_action ("truc", this.truc);
this.add_action ("wala", wala);
this.add_action ("wala", this.wala);
this.add_action ("oupa", this.deleted);
this.error_controller = new CustomErrorController ();
}
/*
......@@ -42,6 +44,10 @@ public class HomeController : Controller {
name = "With the model method !"
}));
}
public Response deleted () {
return error (404, "The page you are looking for doesn't exist anymore.");
}
}
/*
......
......@@ -2,3 +2,14 @@ body {
padding: 20px 30%;
font-family: Arial;
}
input {
display: block;
margin: 10px 0px 30px 0px;
}
.debug {
background: rgb(255, 228, 158);
padding: 20px;
margin: 20px 0px;
}
......@@ -18,13 +18,13 @@ public class UserController : Controller {
this.add_complete_action ("index", list);
this.add_complete_action ("list", list);
this.add_complete_action ("delete", delete, {"id"});
this.add_complete_action ("delete", delete, { "id" });
this.add_complete_action ("create", create);
this.add_complete_action ("register", create);
this.add_complete_action ("view", view, {"id"});
this.add_complete_action ("profile", view, {"id"});
this.add_complete_action ("view", view, { "id" });
this.add_complete_action ("profile", view, { "id" });
// TODO : update
}
......@@ -37,14 +37,7 @@ public class UserController : Controller {
User[] base_arr = new User[] {};
foreach (var user in this.db.all<User> ()) {
Value val = Value (typeof (string));
user.get_property ("avatar", ref val);
print ("in db i have a %s\n", (string) val);
var usr = (User) user;
if (usr == null) {
print ("user is nullllll !\n");
}
print ("in db there is %s, %s, %s, %s\n", usr.pseudo, usr.sign, usr.avatar, usr.website);
base_arr += usr;
}
......
......@@ -3,8 +3,7 @@
<head>
<meta charset="utf-8">
<title>{% zone title %}</title>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="style.lol">
<link rel="stylesheet" href="/style.css">
</head>
<body>
<h1>{% zone title %}</h1>
......
......@@ -5,7 +5,17 @@ All users
{% endzone %}
{% zone body %}
<p>
There is {{ mod.users.count }} users.
</p>
<ul>
{% for user in mod.users %}
<p>{{ user.pseudo }}</p>
<li>{{ user.pseudo }}</li>
{% endfor %}
</ul>
<a href="create">Create a new account</a>
<div class="debug">
<h2>Debug infos</h2>
{{ debug:model }}
</div>
{% endzone %}
using Gee;
using Valse.Default;
namespace Valse {
......@@ -15,11 +16,16 @@ namespace Valse {
*/
public HashMap<string, Action> actions { get; set; default = new HashMap<string, Action> (); }
/*
* The error controller to use with this controller
*/
public ErrorController? error_controller { get; set; default = null; }
/**
* Redirects to a given URL.
*
* @param url The URL on which to redirect.
* @param permanent Tells to the client if it whould always do this redirection without asking anymore. Default to false.
* @param permanent Tells to the client if it whould always do this redirection without asking anymore. Defaults to false.
*/
public Response redirection (string url, bool permanent = false) {
Response res = new Response ();
......@@ -66,6 +72,16 @@ namespace Valse {
return new Response.from_html (Router.options.render_engine.render_page (view));
}
/**
* Displays an error page
*
* @param code The HTTP error code
* @param message A description of the error
*/
public Response error (int code, string? message = null) {
return this.error_controller.error (code, message == null ? get_reason (code) : message);
}
/**
* Creates a model.
*
......@@ -125,7 +141,7 @@ namespace Valse {
result += line + "\n";
}
} catch (Error e) {
error ("%s", e.message);
print ("[ERROR] %s\n", e.message);
}
return result;
......
......@@ -137,7 +137,7 @@ namespace Valse {
int i = 1; // count the number of properties we
foreach (ParamSpec spec in obj.get_class ().list_properties ()) {
// we add some quotes if the value is a text
// we add quotes if the value is a text
if (spec.value_type == typeof (string)) {
vals += "\"";
}
......@@ -277,14 +277,12 @@ namespace Valse {
execute_query (query, (ncol, vals, names) => {
string? first_prop = ""; // object's first property's name
Object obj = Object.new (type);
for (int i = 0; i < ncol; i++) {
// for each result
Type val_type = typeof (string); // the type of the variable to define
foreach (ParamSpec spec in ((ObjectClass) type.class_ref ()).list_properties ()) {
if (first_prop == "") { // we set the name of the first prop, if it isn't already set
first_prop = spec.name.replace ("-", "_");
}
......@@ -294,10 +292,9 @@ namespace Valse {
}
}
// if we are on the first property = we are on a new object
if (first_prop != null && names [i] == first_prop) {
if (first_prop != "" && names[i] == first_prop) {
// we add the old object to the list, and we create a new one
result.add (obj);
obj = Object.new (type);
result.add (Object.new (type));
}
// we set the property
......@@ -305,18 +302,22 @@ namespace Valse {
switch (val.type ().name ()) {
case "gchararray":
val.set_string (vals [i]);
val.set_string (vals[i]);
break;
case "gint":
val.set_int (int.parse (vals [i]));
val.set_int (int.parse (vals[i]));
break;
case "gdouble":
val.set_double (double.parse (vals [i]));
val.set_double (double.parse (vals[i]));
break;
case "GDateTime":
int year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0;
vals[i].scanf ("%d-%d-%d %d-%d-%d.000", ref year, ref month, ref day, ref hour, ref minute, ref second);
DateTime dt = new DateTime.utc (year, month, day, hour, minute, (double) second);
val.set_boxed (dt);
break;
// TODO : handle dates
}
obj.set_property (names [i], val);;
result[result.size - 1].set_property (names[i].replace ("_", "-"), val);
}
return 0;
});
......
......@@ -46,14 +46,14 @@ namespace Valse {
public CustomStaticServer static_server { get; owned set; }
/**
* A list of the static files found at the launch of the server
* The errror controller to use for controller which doesn't have one.
*/
private string[] static_files { get; set; }
public ErrorController error_controller { get; set; default = new ErrorController (); }
/*
* The schema to follow for routing.
/**
* A list of the static files found at the launch of the server
*/
public string[] route_schema { get; set; default = { "{{ controller }}", "{{ action }}", "{{ id }}" }; }
private string[] static_files { get; set; }
/**
* Constructor of the server. Registers some commmons mime-types.
......@@ -179,7 +179,6 @@ namespace Valse {
}
private Response route (Request req) {
Response res = new Response.from_html ("<h1>You found a bug in Valse</h1>");
res.error_code = 500;
string debug_message = "";
......@@ -197,11 +196,10 @@ namespace Valse {
res = this.static_server (req);
} else {
// use the default static server
if ("static/" + req.path in this.static_files) {
if ("static" + req.path in this.static_files) {
try {
uint8[] file_data = "".data;
GLib.FileUtils.get_data ("static/" + req.path, out file_data);
GLib.FileUtils.get_data ("static" + req.path, out file_data);
res.raw_data = file_data;
res.is_data = true;
res.error_code = 200;
......@@ -213,7 +211,7 @@ namespace Valse {
res.headers ["Expires"] = expiration.to_string (DateFormat.HTTP);
res.headers ["Last-Modified"] = new Soup.Date.from_now (-10).to_string (DateFormat.HTTP);
} catch (Error err) {
print ("[ERROR] \"static/%s\" not found.\n", req.path);
print ("[ERROR] \"static%s\" not found.\n", req.path);
res.error_code = 404;
}
}
......@@ -259,11 +257,9 @@ namespace Valse {
} else if (ctrl.actions.has_key ("index")) {
act = "index";
} else {
throw new ValseError.NOT_FOUND ("Can't find the '%s' action.", clean_path[0]);
return ctrl.error_controller.error (404, "Can't find the '%s' action.".printf (clean_path [0]));
}
req.options = clean_path;
res = ctrl.run_action (act, req);
......@@ -292,10 +288,12 @@ namespace Valse {
*/
public void register (string route, Controller controller) {
if (!this.routes.has_key (route)) {
this.routes.set (route, controller);
if (controller.error_controller == null) {
controller.error_controller = this.error_controller;
}
this.routes[route] = controller;
} else {
print ("[ERROR] \"/%s\" has already a controller.\n", route);
return;
}
}
......@@ -310,6 +308,9 @@ namespace Valse {
print ("Development server available at http://127.0.0.1\n");
print ("SimpleCGI listening on port %u\n", this.port);
print ("%d static files found\n", this.static_files.length);
foreach (string file in this.static_files) {
print (" -%s\n", file);
}
print ("Quit the server with CTRL-C\n");
}
MainLoop ml = new MainLoop ();
......
namespace Valse.Default {
/*
* The default error controller.
*
* Use a child class to define custom error pages.
*/
public class ErrorController : Controller {
protected string? error_message { get; set; }
public virtual Response error (int code, string message) {
if (this.actions.has_key (code.to_string ()) && this.actions[code.to_string ()].handler != null) {
this.error_message = message;
var res = this.actions[code.to_string ()].handler ();
this.error_message = null;
return res;
} else {
return new Response.from_html ("<h1>%d: %s</h1>".printf (code, message));
}
}
}
}
......@@ -35,6 +35,7 @@ namespace Valse {
* Custom errors.
*/
public errordomain ValseError {
NOT_FOUND
NOT_FOUND,
SERVER_ERROR
}
}
......@@ -135,10 +135,20 @@ namespace Valse {
string result = view.content;
result = result.replace ("{{ render_engine }}", this.name);
string model_dump = "";
foreach (var model in view.models.entries) {
string model_keyword = model.key;
var mdl = model.value;
foreach (var mod_var in mdl.entries) {
model_dump += @"<p>$(model_keyword).$(mod_var.key) = $(mod_var.value)";
if (mod_var.value == null) {
model_dump += "(null)";
}
model_dump += "</p>";
}
var stre = "{% *for (?P<item>([A-Za-z0-9_]|\\.)*?) in " + model_keyword + "\\.(?P<coll>[[:graph:]]*?) *%}(?P<content>(.|\\R)+?){% *endfor *%}";
Regex for_re = new Regex (stre);
MatchInfo for_info;
......@@ -176,7 +186,7 @@ namespace Valse {
}
// Model variables
Regex var_re = new Regex ("{{ *" + model_keyword + "\\.(?<prop>[A-Za-z0-9_]*)(\\|(?<filter>[[:graph:]]*?)( (?<params>\".*?\"))?)? *}}");
Regex var_re = new Regex ("{{ *" + model_keyword + "\\.(?<prop>[A-Za-z0-9_.\\[\\]]*)(\\|(?<filter>[[:graph:]]*?)( (?<params>\".*?\"))?)? *}}");
MatchInfo var_info;
bool go_var = var_re.match (result, 0, out var_info);
......@@ -329,6 +339,7 @@ namespace Valse {
result = result.replace ("\t", "");
}
result = result.replace ("{{ debug:model }}", model_dump);
return result;
} catch (Error err) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment