librelist archives

« back to archive

Cannot do a catch-all on Host match

Cannot do a catch-all on Host match

From:
tsuraan
Date:
2010-12-30 @ 03:47
I'm trying to set up a host so that it will be used for any incoming
request, whatever the name the user is using to refer to my server.  I
would expect that you could do this using 'matching=""' in the Host
declaration, but that isn't working for me.  My current config (after
playing with the matching declaration for a bit) is this:

servers = [Server(
  uuid="f400bf85-4538-4f7a-8908-67e313d515c2",
  chroot="./",
  access_log="./logs/access.log",
  error_log="./logs/error.log",
  pid_file="./some.pid",
  default_host="myhost",
  port=8080,
  name="myserver",
  hosts = [
    Host(name="myhost",
         matching=".*",
         routes={
             '/' : Proxy(addr='localhost', port=3000),
             '/comet' : Handler(send_spec="tcp://127.0.0.1:9998",
                           send_ident="sender",
                           recv_spec="tcp://127.0.0.1:9999",
                           recv_ident="sender")
                                })])]

Any attempt to contact the server gives a 404 on the client, and this
message on mongrel2:

src/connection.c:104: errno: Resource temporarily unavailable) Request
for a host we don't have registered: localhost

A sample telnet looks like this:

GET / HTTP/1.1
Host: localhost

HTTP/1.1 404 Not Found
Content-Type: text/plain
Connection: close
Content-Length: 9
Server: Mongrel2/1.4-561cb4b4a4

Not Found

If I instead use "myhost" as the Host, it does work as it should.  Is
the matching directive being ignored, or is it broken in the random
fossil checkout that I grabbed, or am I doing something wrong?

Re: [mongrel2] Cannot do a catch-all on Host match

From:
Zed A. Shaw
Date:
2010-12-30 @ 10:06
On Wed, Dec 29, 2010 at 09:47:19PM -0600, tsuraan wrote:
> I'm trying to set up a host so that it will be used for any incoming
> request, whatever the name the user is using to refer to my server.  I
> would expect that you could do this using 'matching=""' in the Host
> declaration, but that isn't working for me.  My current config (after
> playing with the matching declaration for a bit) is this:

Try this:

main = Server(
    uuid="5c7e6342-88c5-44d0-ad9a-3526128039a1",
    access_log="/logs/access.log",
    error_log="/logs/error.log",
    chroot="./",
    default_host="(.+)",
    name="test",
    pid_file="/run/mongrel2.pid",
    port=6767,
    hosts = [
        Host(name="(.+)", routes={
        })
    ]
)

servers = [main]

Just use a (.+) pattern which matches everything, then say that's the
default host.

-- 
Zed A. Shaw
http://zedshaw.com/

Re: [mongrel2] Cannot do a catch-all on Host match

From:
tsuraan
Date:
2010-12-30 @ 15:35
> Try this:
>
> main = Server(
>    uuid="5c7e6342-88c5-44d0-ad9a-3526128039a1",
>    access_log="/logs/access.log",
>    error_log="/logs/error.log",
>    chroot="./",
>    default_host="(.+)",
>    name="test",
>    pid_file="/run/mongrel2.pid",
>    port=6767,
>    hosts = [
>        Host(name="(.+)", routes={
>        })
>    ]
> )

Ok, that does seem to work.  Why does setting name to a pattern work,
but setting matching to the same pattern not?  Is that just a bug?

Re: [mongrel2] Cannot do a catch-all on Host match

From:
Zed A. Shaw
Date:
2010-12-30 @ 19:09
On Thu, Dec 30, 2010 at 09:35:16AM -0600, tsuraan wrote:
> Ok, that does seem to work.  Why does setting name to a pattern work,
> but setting matching to the same pattern not?  Is that just a bug?

Not sure what you mean, why don't you write out what you think should be
happening.  That might be a better way to try to understand what's going
on.  For example:

"I think that mongrel2 should do:

1. A request comes in for foobarbaz.com.
2. There is a host named "(.+)".
..."


-- 
Zed A. Shaw
http://zedshaw.com/

Re: [mongrel2] Cannot do a catch-all on Host match

From:
tsuraan
Date:
2010-12-31 @ 04:09
> Not sure what you mean, why don't you write out what you think should be
> happening.  That might be a better way to try to understand what's going
> on.  For example:
>
> "I think that mongrel2 should do:
>
> 1. A request comes in for foobarbaz.com.
> 2. There is a host named "(.+)".
> ..."

Given a Host with both a name and a matching declaration, like so:

...
Host(name="bob",
        matching="(.*)",
        ...

So the host's name is bob, but his matching spec should match
anything.  In the absence of any other hosts, I would expect any
request to be routed to this host.  If there were some other hosts,
with more specific matching declarations (or host names) that match
the request, then I would expect the request to be dispatched to those
other hosts.  So, I guess my understanding (misunderstanding?) was
that the name was used for matching unless a matching declaration was
given; if a matching declaration is given, then I thought the host
part would be ignored, or at least not be exclusively used for
matching requests against hosts.  Does that make sense?

Re: [mongrel2] Cannot do a catch-all on Host match

From:
tsuraan
Date:
2011-01-07 @ 20:33
>> Not sure what you mean, why don't you write out what you think should be
>> happening.  That might be a better way to try to understand what's going
>> on.  For example:
>>
>> "I think that mongrel2 should do:
>>
>> 1. A request comes in for foobarbaz.com.
>> 2. There is a host named "(.+)".
>> ..."
>
> Given a Host with both a name and a matching declaration, like so:
>
> ...
> Host(name="bob",
>        matching="(.*)",
>        ...
>
> So the host's name is bob, but his matching spec should match
> anything.  In the absence of any other hosts, I would expect any
> request to be routed to this host.  If there were some other hosts,
> with more specific matching declarations (or host names) that match
> the request, then I would expect the request to be dispatched to those
> other hosts.  So, I guess my understanding (misunderstanding?) was
> that the name was used for matching unless a matching declaration was
> given; if a matching declaration is given, then I thought the host
> part would be ignored, or at least not be exclusively used for
> matching requests against hosts.  Does that make sense?

Just noticed that Zed is still alive, so re-sending this in case it
got lost in transit or something.

Re: [mongrel2] Cannot do a catch-all on Host match

From:
Zed A. Shaw
Date:
2011-01-07 @ 21:07
On Fri, Jan 07, 2011 at 02:33:45PM -0600, tsuraan wrote:
> > So the host's name is bob, but his matching spec should match
> > anything.  In the absence of any other hosts, I would expect any
> > request to be routed to this host.  If there were some other hosts,
> > with more specific matching declarations (or host names) that match
> > the request, then I would expect the request to be dispatched to those
> > other hosts.  So, I guess my understanding (misunderstanding?) was
> > that the name was used for matching unless a matching declaration was
> > given; if a matching declaration is given, then I thought the host
> > part would be ignored, or at least not be exclusively used for
> > matching requests against hosts.  Does that make sense?
> 
> Just noticed that Zed is still alive, so re-sending this in case it
> got lost in transit or something.

Yes, this is too complicated I think.  It's literally:

1. Request comes in for a host to the port.
2. Server listening on that port runs the Host.name against the routing
list.
3. If it finds a match (by name), it uses that Host.
4. If not, it uses the host set in Server.default_host.

I think the confusion is the existence of Host.name and Host.matching,
so probably need a ticket for making one of those not exist or
clarifying it.

-- 
Zed A. Shaw
http://zedshaw.com/

Re: Cannot do a catch-all on Host match

From:
tsuraan
Date:
2010-12-30 @ 03:57
> I'm trying to set up a host so that it will be used for any incoming
> request, whatever the name the user is using to refer to my server.  I
> would expect that you could do this using 'matching=""' in the Host
> declaration, but that isn't working for me.  My current config (after
> playing with the matching declaration for a bit) is this:

Poking around a bit, the config I gave results in this hosts table:

sqlite> select * from host;
1|1|0|myhost|myhost

So, my matching declaration isn't being set.  If I do set matching to
an empty string, or a string that is simply '.', I still get the
unregistered host error when I make a request with the Host set to
anything other than myhost.  So, even though matching is set to
something other than myhost, myhost is the only host that mongrel2
will accept.  I'll keep poking around.

Re: Cannot do a catch-all on Host match

From:
tsuraan
Date:
2010-12-30 @ 04:21
> sqlite> select * from host;
> 1|1|0|myhost|myhost
>
> So, my matching declaration isn't being set.  If I do set matching to
> an empty string, or a string that is simply '.', I still get the
> unregistered host error when I make a request with the Host set to
> anything other than myhost.  So, even though matching is set to
> something other than myhost, myhost is the only host that mongrel2
> will accept.  I'll keep poking around.

Ok, so aside from the problem with the matching column of the table
not being set by m2sh, it doesn't look like the host matching uses
patterns, as described in the "Routing and Host Patterns" section of
the m2 book.  If I set the match to '.', then any Host that ends with
a "." character is matched with my Host declaration, but the "." is
not acting as a wildcard character.  The RouteMap_match_suffix
function calls tst_search_suffix, which doesn't appear to have any
sort of pattern expansion built into it.  Is this a bug, or a
mis-reading of the manual?  Also, it still seems like
tst_search_suffix should match any string against an empty string, but
it doesn't.  More poking around to come :)

Re: Cannot do a catch-all on Host match

From:
tsuraan
Date:
2010-12-30 @ 04:47
> Ok, so aside from the problem with the matching column of the table
> not being set by m2sh, it doesn't look like the host matching uses
> patterns, as described in the "Routing and Host Patterns" section of
> the m2 book.  If I set the match to '.', then any Host that ends with
> a "." character is matched with my Host declaration, but the "." is
> not acting as a wildcard character.  The RouteMap_match_suffix
> function calls tst_search_suffix, which doesn't appear to have any
> sort of pattern expansion built into it.  Is this a bug, or a
> mis-reading of the manual?  Also, it still seems like
> tst_search_suffix should match any string against an empty string, but
> it doesn't.  More poking around to come :)

I looked at the docs again, and I think the match that I'm looking for
should be "(.)" or "(.*)", not just ".".  Neither of those work for me
though.

Looking more into why empty strings don't work, I found that if the
string being inserted into the tst (using tst_insert) is blank, then
its len is 0 and (I think) the *s in the tst_insert_base function is
always 0.  So, we're inserting a node with splitchar equal to 0.  That
would probably be ok, if the tst_search_suffix function started
looking at the null character at the end of the string, and if the
RouteMap_insert_reversed always made sure that the leading character
of the reverse strings was 0.  To test it out, I modified adt/tst.c
line 99, making it say "int i = len" rather than len-1, and it does
match strings against the empty pattern :)  Of course, without
changing RouteMap_insert_reversed it breaks the unit tests, which
isn't so good, so it's not a fix yet.  Is this a reasonable direction
to go in, or should we just use lua patterns?