2

I have got follow code:

import std.stdio;
import database;
import router; 
import config;
import vibe.d;

void main()
{
    Config config = new Config();
    auto settings = new HTTPServerSettings;
    settings.port = 8081;
    settings.bindAddresses = ["::1", "127.0.0.1"];

    auto router = new URLRouter();
    router.get("/*", serveStaticFiles("./html"));

    Database database = new Database(config);
    database.MySQLConnect(); // all DB methods are declared here

    router.registerRestInterface(new MyRouter(database));
    router.get("*", &myStuff); // all other request
    listenHTTP(settings, router);

    logInfo("Please open http://127.0.0.1:8081/ in your browser.");
    runApplication();

}


void myStuff(HTTPServerRequest req, HTTPServerResponse res) // I need this to handle any accessed URLs
{
    writeln(req.path); // getting URL that was request on server
    // here I need access to DB methods to do processing and return some DB data
}

I was needed create router.get("*", &myStuff); to process any urls, that do not relate to any REST instance.

The problem that I do not know how to get access to DB methods from myStuff()

Dmitry Bubnenkov
  • 9,415
  • 19
  • 85
  • 145

3 Answers3

1

Haven't tried it but using 'partial' might be a solution.

https://dlang.org/phobos/std_functional.html#partial

void myStuff(Database db, HTTPServerRequest req, HTTPServerResponse res) { ... }

void main()
{
    import std.functional : partial;

    ...
    router.get("*", partial!(myStuff, database));
    ...
}

Partial creates a function with the first parameter bound to a given value - so the caller does not need to know about it. Personally I don't like globals/, singletons/ etc. and try to inject dependencies. Although the implementation might become a bit more complex this really simplifies testing a lot.

The example above injects dependencies in a way similar to Constructor Injection as mentioned here:

https://en.wikipedia.org/wiki/Dependency_injection#Constructor_injection

When injecting dependencies like this you also get a quick overview about the required components to call this function. If the number of dependencies increases think of using other approaches - eg. inject a ServiceLocator.

https://martinfowler.com/articles/injection.html#UsingAServiceLocator

Ronny

duselbaer
  • 935
  • 2
  • 6
  • 10
1

As an alternative to partial, you could achieve partial application with a closure:

router.get("*", (req, resp) => myStuff(database, req, resp));

// ...

void myStuff(Database db, HTTPServerRequest req, HTTPServerResponse res)

// ...

myStuff now has database injected from the surrounding scope.

rcorre
  • 6,477
  • 3
  • 28
  • 33
0

I have no experience with vibe.d, but this may be one solution:

Database database;

shared static this(){
    Config config = new Config();
    database = new Database(config);
}

void main(){
(...)

void myStuff(HTTPServerRequest req, HTTPServerResponse res){
    database.whatever;
}
Patric
  • 763
  • 1
  • 8
  • 17