Close
Community Post

Two generic approaches to the WebServerDAT

I have come to work more and more using webtechnologies. I also have a little course for intermidiate users of TouchDesigner explaining the basics of fetching data from webAPIs over at the Node Institute.
But requests have far more utilities then fetching data from some random server in the web. It is a reliable, system agnostic and industrie proven way to transport data of all forms and shapes with thousands of libraries, modules and more for all kind of languages. So, to no supries, Derivative introduced the WebServerDAT arround one year arround with a little sidenote in an experimental release. And that was good news (at least for me).

Request?

But first we have to get a little idea of how all of this works. I will not go to deep into the specifics, but the basic idea behind the web for a long time (and still to this day) is that we open a channel to our server, send some information, and receive a response. After this is set and done, the channel gets closed and client and server do not know anything of one another. (The opposite to this are websockets, which opens a channel and can send and receive information from both side until one of the two participants decide to close the connection.) The awsome thing is that we can always know the request/response pairing and we do not have to take care of tracing messages or keeping track of logged in users. After the deal is sealed, we do no longer care about the client.

A request can carry different information. The uri (the part after the address of a url), a method (what do we want to do?) and, depending on the method, a body with data from the client.
A response looks very similiar, carrying data, a status code (who does not love a 404?) and some more info in the header.

The two most important request methods for the beginning are POST and GET. All the other ones are somewhat similiar to this two.

A GET request is the default method we use all the time. It does not carry any additional data except the uri (and query params, but I don't care about them today.) It basicly says
SERVER, GIVE ME WHAT IS IN THIS LOCATION!

The POST method can carry alot more data as you can define a body. A body can hold basicly anything, a JSON formatted string or the bytedata of the last image you took of your cat. This method tells the server
SERVER, I HAVE SOMETHING FOR YOU! DO WHAT I SAY YOU SHOULD DO WITH IT!

 

So, how das this help us in TouchDesigner?

The general purpose webserver-comp

The general prupose webserver is an extremly powerfull component and a plug and play approach, giving a lot of power to the clientside.
First thing is hosting of files. We want to be able to host data directly from touch, but maybe we also have a webdeveloper creating an awsome site using some framework. For this to work we also want to define an external source. And it is suprisingly easy. Drop the generalPurposeWebserver in your project, define the root folder and component and it runs all by itself.

Thats it, when we now go to localhost:9984/content in a browser, the generalPurposeWebserver will return the textcontent of the conten-dat. In this, we are refferencing the butterfly-top, which automaicaly gets encoded as a png image and displayed by the browser.

 

As another example I placed the content-dat in a folder called Website (refferenced in the general purpose webserver) with the name index.html and the butterfly in a the folder media. Changing the path in our new html file to point to that new butterfly path and voila, we got another butterfly.

But this is not what this baby is made for. The much more interresting part are the POST requests. They allow you to call methods from any component in your defined network. Any!

So lets create a new component named myCustomComponent and create an extension for it. In this extension we define a new method:

	def SetNodeColor(self, red, green, blue):
		self.ownerComp.color = (red, green, blue)

On client side I'm going to use default fetch statement native in JavaScript, but this can also be done, for example using the webclient dat. We will send a POST request using the dot-notation and in the body we are going to attach a json string with the arguments of the method as key-value pairs.

let arguments = { "red"   : 1,
                  "green" : 0,
                  "blue"  : .5, }

      fetch( "localhost:9984/myCustomComponent.SetNodeColor",
              { method: "POST",
                body: JSON.stringify( arguments ),} 
            );

And the node turns into a nice pink the moment we send that that request.

The best part is, that if we should return a value, the returnvalue will be sent to the client in the response. For example, the TauCeti Presetmanager has a GetPresetJson method to fetch all the possible presets. Neat, right?

 

Routed webserver

The second approach I discovered for myself is using a routed server. Here, we define specific routes, and attach a seperate handlerfunction to it. This approach gives the developer a much more granular way of handling requests. So, lets take a look inside! In the server we will find two dats. The routes and handler dat.
The routes define the specific endpoints. When we start one part of the URI with a :, this will count as a wildcard and the value standing there will be passed down to our handler in the route_parameter argument.
import handler
routes = { "GET" : 	{ "/helloworld" 	: handler.all_ok,
			"/print/:value" 	: handler.printme },
					} 
def all_ok(uri_parameter, route_parameter, parsed_body):
	return "All Fine!"
 
def printme(uri_parameter, route_parameter, prased_body):
	print("Someone wants you to see this:", route_parameter["value"])
	return "Your message was delivered"
So now, lets call our webserver on
http://localhost:9475/helloworld

A nice "All Fine!" will be displayed.

But what happens when we call, for example,

http://localhost:9475/print/ThisIsAwsome

For one it will now display "Your message was delivered" but also the textport in TouchDesigner now printed

Someone wants you to see this: ThisIsAwsome

You can also attach query-parameter to the url using

http://localhost:9475/print/ThisIsAwsome?really=yes

and acces them in your handler from the uri_parameter argument. Same goes for the parsed_body. Send a POST-request with a JSON-String to acces it as a dictionary from the parsed_body argument.


I hope this writeup was interresting. Both servers will be attached in the first comment of this post to play arround with. They are something I use myself but not directly meant as a production ready tool. See them as a baseline to get a better idea of how to interact with TouchDesigner using webtechnologies.