ufront / ufront-mvc

The core MVC framework that powers ufront
MIT License
17 stars 15 forks source link

APIs that are submodules do not work with remoting #29

Closed jasononeil closed 9 years ago

jasononeil commented 9 years ago

If a UFApi class has a name that is different to the filename (eg class NekoApi is inside HelloWorld.hx) then the UFAsyncApi on the client will request HelloWorld.NekoApi.sum() but the server only knows that API as NekoApi.sum(), it results in a 404 not found on the remoting request.

Full reproducible code (used in the HelloWorld project with same views/hxmls etc):

import ufront.MVC;
import tink.core.Error;
import tink.core.Future;
import tink.core.Outcome;

/**
This is an example of how to initiate and execute a Ufront app.
The process differs slightly between client and server.
**/
class NekoApi extends UFApi {
    public function sum(a:Int,b:Int):Int {
        trace(333);
        return a+b;
    }
}

class AsyncNekoApi extends UFAsyncApi<NekoApi> {}

class NekoRemotingContext extends UFApiContext {
     var nekoApi:NekoApi;
}

class HelloWorld {
    static function main() {
        #if server
            // Initialise the app on the server and execute the request.
            var ufApp = new UfrontApplication({
                indexController: HelloWorldController,
                defaultLayout: "layout.html",
                remotingApi: NekoRemotingContext
            });
            #if (php || neko)
                ufApp.executeRequest();
            #elseif nodejs
                ufApp.listen();
            #end
        #elseif client
            // Initialise the app on the client and respond to "pushstate" requests as a single-page-app.
            var clientApp = new ClientJsApplication({
                indexController: HelloWorldController,
                defaultLayout: "layout.html",
                remotingPath:'/'
            });
            clientApp.listen();
        #end
    }
}

/**
This is a very basic controller, that responds to URL routes and returns a view.
See `www/views/` for the HTML views we are using, using the default `haxe.Template` templating engine.
**/
class HelloWorldController extends Controller {
    @inject public var nekoApi:AsyncNekoApi;

    @:route("/$name") public inline function hello(?name:String = "ddd") {
        ufTrace( 'Hey $name, did you know we can trace directly to the browser console?' );
        var date = Date.now().toString();
        var f = Future.trigger();
        var partial = new PartialViewResult({
            title:'$name $date'
        },"hello.html");
        #if js
            haxe.Timer.delay(function() {
                nekoApi.sum(1,2).handle(function(x) {
                    ufTrace(x);
                    return x;
                });
                f.trigger(Success(partial));
            },0);
        #else
            nekoApi.sum(1,2);
            f.trigger(Success(partial));
        #end
        return f.asFuture();
    }

    @:route(GET,"/signup/newname/") public function newNameForm() {
        return new ViewResult({
            title:"Custom name"
        });
    }

    @:route(POST,"/signup/newname/") public function submitNewName( args:{name:String} ):ActionResult {
        if ( args.name.length>0 ) {
            return new RedirectResult( '/${args.name}/' );
        } else {
            return new ViewResult({
                title:"Custom name",
                error: "Please include your name"
            }, "newNameForm");
        }
    }
}

Reported by @francescoagati on Gitter: https://gitter.im/ufront/ufront?at=55d4f9e31ba62e4a21fa74dd