gotlium/madfish-webtoolkit

For urls with partially matched names dispatcher always calls method registered for shorter

GoogleCodeExporter opened this issue · 0 comments

Sorry, not even sure if this project is at least partially supported so I just 
leave here short description and solution... Just in case.

So, for urls like /url and /url1 no mater what you add for mapping allways will 
be called method mapped for /url
dispatcher.AddMapping("/url", HttpPost, new 
HttpHandlerConnector<VoteServer>(this,&VoteServer::urlMethod), true);
dispatcher.AddMapping("/url1", HttpPost, new 
HttpHandlerConnector<VoteServer>(this,&VoteServer::url1Method), true);
So if I access http://serverip:serverport/url1 VoteServer::url1Method will be 
called. 

This happens cause URIDispatcher::Handle method checks length bla bla bla you 
know it yourself. So there is a very easy solution. Cause map orders methods by 
string length (actually alphabetically but whatever) and url is actually 
dispatchMap key reversing dispatchMap iteration solves everything. Methods are 
now iterated from longest to shortest. 

So here are the fixes. Basically I just changed iterator to reverse_iterator 
and begin() end() to rbegin() rend(). And just in case made the same changes 
for HostDispatcher.


void HostDispatcher::Handle(HttpServerContext* context)
{
    for(map<string,Mapping>::reverse_iterator iter=dispatchMap.rbegin();iter!=dispatchMap.rend();iter++)
    {
        if((context->requestHeader.host.length()>=iter->first.length())&&(context->requestHeader.host.compare(context->requestHeader.host.length()-iter->first.length(),iter->first.length(),iter->first)==0))
        {
            context->requestHeader.host.erase(context->requestHeader.host.length()-iter->first.length());
            if(context->requestHeader.host[context->requestHeader.host.length()-1]=='.')
                context->requestHeader.host.resize(context->requestHeader.host.length()-1);
            Invoke(iter->first,context);
            return;
        }
    }
    if(!defaultHandler.empty())
        Invoke(defaultHandler,context);
    else
        throw HttpException(HttpNotFound,"Not found.");
}

void URIDispatcher::Handle(HttpServerContext* context)
{
    for(map<string,Mapping>::reverse_iterator iter=dispatchMap.rbegin();iter!=dispatchMap.rend();iter++)
    {
        if((context->requestHeader.resource.length()>=iter->first.length())&&(context->requestHeader.resource.compare(0,iter->first.length(),iter->first)==0))
        {
            context->requestHeader.resource.erase(0,iter->first.length());
            Invoke(iter->first,context);
            return;
        }
    }
    if(!defaultHandler.empty())
        Invoke(defaultHandler,context);
    else
        throw HttpException(HttpNotFound,"Not found.");
}

Hope this will help...

Good luck!

Original issue reported on code.google.com by alexandr...@gmail.com on 29 May 2013 at 11:57