Skip to content

Using Diamond : Webservice

Jacob Jensen edited this page May 22, 2016 · 10 revisions

To use Diamond for a webservice you must have dub installed.

If it's the first time you use Diamond, then it's recommended to follow the guide below.

If you're already familiar with Diamond then an empty project corresponding the below can be found here:

https://github.com/bausshf/DiamondEmptyService

Just download the project as zip.

Create a new folder for your project. Ex. diamondproject

Create the following folders and files within it. (Don't worry about content right now.)

  • \diamondproject
    • \config
      • web-build.json
    • \controllers
      • package.d
      • testcontroller.d
    • \core
      • web.d
    • \models
      • package.d
      • test.d
    • dub.json
    • web-runtime.json

Below is all the content for the files. Just copy-paste it into the files. Explanations of them are right below.

dub.json

{
	"name": "diamondproject",
	"description": "A diamond webservice project",
	"authors": ["Jacob Jensen"],
	"homepage": "http://mydiamondwebsiteproject.com/",
	"license": "http://mydiamondwebsiteproject.com/license",
	"dependencies": {
		"vibe-d": "~>0.7.28",
		"diamond": "~>0.2.32"
	},
	"versions": ["VibeDefaultMain", "WebService"],
	"sourcePaths": ["core", "models", "controllers"],
	"stringImportPaths": ["config"],
	"targetType": "executable"
}

name is the name of the project.

description is the description of the project.

authors is the authors of the project.

homepage is the homepage of the project.

license is the license of the project.

dependencies is the dependencies of the project. A webservice using Diamond has a dependency to vibe.d

versions are all versions to compile with. For a webservice you must compile with "WebService"

sourcePaths are all paths that dub will look for code. By defualt Diamond only uses core, models and controllers.

stringImportPaths are all paths dub will look for string imports. By default Diamond only uses config.

targetType are the type of the output. For a Diamond project, it'll typically be executable.

web-runtime.json

{
  "bindAddresses": [
	"::1",
	"127.0.0.1"
  ],
  "port": 8080,
  "defaultHeaders": {
	"Content-Type": "text/html; charset=UTF-8",
	"Server": "vibe.d - Diamond MVC/Template Framework"
  }
}

bindAddresses are all addresses that should bound to.

port is the port that should be bound to.

defaultHeaders are all default headers to append to the responses headers.

The web-runtime.json file must be placed in the same folder as the compiled executable.

config\web-build.json

{
  "name": "diamondproject",
  "controllers":[
	"Test"
  ]
}

name is the name of the project.

controllers are all the controllers associated with the project.

controllers\package.d

module controllers;

public {
  import controllers.testcontroller;
}

You must import all controller modules within this file. Otherwise Diamond will be unable to locate your controllers.

controllers\testcontroller.d

/**
* Module for the test controller.
*/
module controllers.testcontroller;

import vibe.d;

import diamond.controllers;

/// The controller for the test route.
final class TestController : Controller {
  public:
  final:
  /**
  * Creates a new instance of the test controller.
  * Params:
  *   request =		The request.
  *	  response =	The response.
  *	  route =		The route.
  */
  this(HTTPServerRequest request, HTTPServerResponse response, string[] route) {
	super(request, response, route);
	
	mapAction(HTTPMethod.GET, "JsonTest", &jsonTest);
	mapAction(HTTPMethod.GET, "JsonTest2", &jsonTest2);
  }

  private:
  /// Route: /Test/JsonTest
  Status jsonTest() {
	return jsonString(q{{
		"name": "Jacob",
		"age": 23,
		"gender": "male"
	}});
  }

  /// Route: /Test/JsonTest2
  Status jsonTest2() {
	  	import models;

	  	return json(new Test("Hello Diamond!", 42));
  }
}

The constructor of a controller should be used to map actions. For more information view the Diamond documentation.

All controller methods must return "Status" which indicates the status of the call.

Controllers are automatically instantiated internally by Diamond.

core\web.d

module web;

import vibe.d;

import diamond.configurations.websettings;

class DiamondProjectSettings : WebSettings {
	public:
	this() {
		super();
	}
	
	override bool onBeforeRequest(HTTPServerRequest request, HTTPServerResponse response) {
		return true;
	}
	
	override void onAfterRequest(HTTPServerRequest request, HTTPServerResponse response) {
		// ...
	}
	
	override void onHttpError(HTTPServerRequest request, HTTPServerResponse response, HTTPServerErrorInfo error) {
		import diamondapp : serverSettings;

		foreach (headerKey,headerValue; serverSettings.defaultHeaders) {
			response.headers[headerKey] = headerValue;
		}

		response.statusCode = error.code;
		response.bodyWriter.write(error.exception.toString());
	}
}

shared static this() {
	WebSettings.initialize(new DiamondProjectSettings);
}

The web module should be used to declare internal configurations or handle specific "events".

You can use onBeforeRequest to process requests before they start handling stuff such as controller actions etc.

You can use onAfterRequest to process sucessfully handled requests before the response is sent.

You can use onHttpError to handle errors. This is typically used to generate the error response

models\package.d

module models;

public {
  import models.test;
}

For webservices it isn't necessary to declare models in the models package, however it is good practice.

models\test.d

/**
* Module for the test model.
*/
module models.test;

/// Test model.
class Test {
  public:
  /// foo.
  string foo;
  /// bar.
  int bar;

  /**
  * Creates a new instance of the test model.
  * Params:
  *   foo = Foo.
	  *   bar = Bar.
  */
  this(string foo, int bar) {
	this.foo = foo;
	this.bar = bar;
  }
}

Building

To compile the project simply use the following dub command

dub build