RejectedSoftware Forums

Sign up

Bool array in web interface: possible bug?

In my previous post, I wrote about problem with bool array.
I have examined in depth my issue, and the behavior is odd.

I've this code copied from vibe.d/examples/web:

module app;
import vibe.d;

class SampleService {
   // "GET /"
   @path("/") void getHome() {
      render!("home.dt");
   }

   // POST /settings
   void postSettings(string[] x) {
      foreach (i, v; x) {
         logInfo("x[%s]=%s", i, v);
      }
      redirect("./");
   }
}

shared static this() {
   auto router = new URLRouter;
   router.registerWebInterface(new SampleService);
   router.get("*", serveStaticFiles("public/"));

   auto settings = new HTTPServerSettings;
   settings.port = 8080;
   settings.bindAddresses = ["::1", "127.0.0.1"];
   settings.accessLogToConsole = true;
   listenHTTP(settings, router);

   logInfo("Please open http://127.0.0.1:8080/ in your browser.");
}

with this template:

// home.dt
doctype html
html
   head
      title Sample service
   body
      form(method="POST", action="settings")
         div
            label Some setting 0
            input(name="x_0", type="checkbox")
            label Some setting 1
            input(name="x_1", type="checkbox")
            label Some setting 2
            input(name="x_2", type="checkbox")
         div
            button(type="sumbit") OK

and all works well:

127.0.0.1 - - 2015-Oct-09 07:01:38.446259Z "GET / HTTP/1.1" 200 457 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:41.0) Gecko/20100101 Firefox/41.0"

x[0]=on

127.0.0.1 - - 2015-Oct-09 07:01:40.973303Z "POST /settings HTTP/1.1" 302 14 "http://127.0.0.1:8080/" "Mozilla/5.0 (X11; Linux x86_64; rv:41.0) Gecko/20100101 Firefox/41.0"

so, if I change

void postSettings(string[] x) {

to

void postSettings(bool[] x) {

when I click submit the server freezes.

Thank you...

Re: Bool array in web interface: possible bug?

On Fri, 09 Oct 2015 07:27:00 GMT, o3o wrote:

(...)

void postSettings(bool[] x) {

when I click submit the server freezes.

Thank you...

That's indeed a bug. The problem is that the two definitions for handling "array" and "boolean" parameters don't fit together. The rule for dynamic arrays is to continue to gather values until a certain index doesn't exist anymore in the submitted form. However, checkbox/boolean values are transmitted with "true === field is submitted" and "false === field is not submitted", so it's not possible to determine the end of the array unambiguously.

The question is if there is any meaningful way to express bool[] on the form level at all. If not, there should be a compile time error. An alternative is to add support for static arrays (bool[2]), which I did now with 92f4ae0.

Another possibility is to enable an alternative mode for dynamic array parameters, where the same field name can be used multiple times. The example could then look similar to this:

@multiField!"x"
void postSettings(string[] x)
{
// x is something like ["foo", "baz"]
}
form(action="settings", method="POST")
input(type="checkbox", name="x", value="foo")
input(type="checkbox", name="x", value="bar")
input(type="checkbox", name="x", value="baz")
button(type="submit") OK

Not sure if there is a more elegant way to enable that mode other than the attribute based solution above...

Re: Bool array in web interface: possible bug?

Am Fri, 09 Oct 2015 19:21:40 GMT
schrieb "Sönke Ludwig" sludwig@rejectedsoftware.com:

On Fri, 09 Oct 2015 07:27:00 GMT, o3o wrote:

(...)

void postSettings(bool[] x) {

when I click submit the server freezes.

Thank you...

That's indeed a bug. The problem is that the two definitions for
handling "array" and "boolean" parameters don't fit together. The
rule for dynamic arrays is to continue to gather values until a
certain index doesn't exist anymore in the submitted form. However,
checkbox/boolean values are transmitted with "true === field is
submitted" and "false === field is not submitted", so it's not
possible to determine the end of the array unambiguously.

The check_box helper Rails inserts a hidden field with the same name
as the check box and the value "0" before the actual check box. Because
form fields are guaranteed to be submitted in order, an unchecked
checkbox submits as key=0 and a checked one as key=0&key=1, the "1"
overwriting the "0".

The question is if there is any meaningful way to express bool[] on
the form level at all. If not, there should be a compile time error.
An alternative is to add support for static arrays (bool[2]), which
I did now with
92f4ae0.

Another possibility is to enable an alternative mode for dynamic
array parameters, where the same field name can be used multiple
times. The example could then look similar to this:

@multiField!"x"
void postSettings(string[] x)
{
// x is something like ["foo", "baz"]
}
form(action="settings", method="POST")
input(type="checkbox", name="x", value="foo")
input(type="checkbox", name="x", value="bar")
input(type="checkbox", name="x", value="baz")
button(type="submit") OK

I find the current scheme rather bizarre. Why wasn't the "normal"
convention that basically everyone else uses adapted? That is:

key=value			scalar
key[]=value1&key[]=value2	normal array
key[a]=value1&key[b]=value2	associative array

Re: Bool array in web interface: possible bug?

Am 10.10.2015 um 21:46 schrieb Marc Schütz:

Am Fri, 09 Oct 2015 19:21:40 GMT
schrieb "Sönke Ludwig" sludwig@rejectedsoftware.com:

On Fri, 09 Oct 2015 07:27:00 GMT, o3o wrote:

(...)

void postSettings(bool[] x) {

when I click submit the server freezes.

Thank you...

That's indeed a bug. The problem is that the two definitions for
handling "array" and "boolean" parameters don't fit together. The
rule for dynamic arrays is to continue to gather values until a
certain index doesn't exist anymore in the submitted form. However,
checkbox/boolean values are transmitted with "true === field is
submitted" and "false === field is not submitted", so it's not
possible to determine the end of the array unambiguously.

The check_box helper Rails inserts a hidden field with the same name
as the check box and the value "0" before the actual check box. Because
form fields are guaranteed to be submitted in order, an unchecked
checkbox submits as key=0 and a checked one as key=0&key=1, the "1"
overwriting the "0".

Hm... that's a possibility, but I can't say that I'm particularly
thrilled, especially without a form generator that assists in getting
this right. But at least it's a solution...

Emitting a hidden "x.length" field that contains the count would be
another option.

The question is if there is any meaningful way to express bool[] on
the form level at all. If not, there should be a compile time error.
An alternative is to add support for static arrays (bool[2]), which
I did now with
92f4ae0.

Another possibility is to enable an alternative mode for dynamic
array parameters, where the same field name can be used multiple
times. The example could then look similar to this:

@multiField!"x"
void postSettings(string[] x)
{
// x is something like ["foo", "baz"]
}
form(action="settings", method="POST")
input(type="checkbox", name="x", value="foo")
input(type="checkbox", name="x", value="bar")
input(type="checkbox", name="x", value="baz")
button(type="submit") OK

I find the current scheme rather bizarre. Why wasn't the "normal"
convention that basically everyone else uses adapted? That is:

key=value			scalar
key[]=value1&key[]=value2	normal array
key[a]=value1&key[b]=value2	associative array

It's just historically based. The ancestor of the current module was
registerFormInterface, which was made by a contributor who disappeared
after a while. When I started to create the successor module, basic
compatibility was a priority.

I had already started to implement the above scheme last year in a
branch, but was never able to merge the changes due to other changes
getting in the way (I've deleted the branch now and it needs to be
redone). My proposal is to implement some transitional steps:

  1. Add a WebInterfaceSettings.fieldNamingScheme enum that defaults to
    FieldNamingScheme.legacyDefault.
  2. Emit a deprecation warning if the default isn't explicitly set to
    either .dStyle or .underscore
  3. Switch the default to .dStyle

(enum names subject to change...)

It's not seamless, but at least there won't be any silent breakage.