XTCLANG GUIDES
How to Set Up a Web Server and Client in Ecstasy
xtclang
client-server
class keywords
example
Authored by: Abby Sassel
Last edited: @May 6, 2024
About this guide
In this guide, we'll set up a basic web client and server example, highlighting some core Ecstasy language concepts along the way.
Topics:
- Implementing an HTTP Server and Client in Ecstasy
- Annotations with examples
- Class Keywords with examples
Target Audience
This guide is suitable for beginners to the Ecstasy language with a high-level familiarity with the client-server network model.
Prerequisites
Go to https://github.com/xtclang/xvm#installation and follow the appropriate steps to install the Ecstasy toolchain for your system.
To verify the installation, run the xec
(Ecstasy execution command) and xcc
(Ecstasy compilation command) in your terminal with no arguments. Both should display documentation and available options for their respective commands.
The HelloServer
Module
Let's look at the working web server example:
https://github.com/xtclang/xvm/blob/master/xdk/src/main/resources/xdk/examples/HelloServer.x
// Annotate the `HelloServer` module indicating that this is a web application containing discoverable HTTP endpoints
@WebApp
// Define a module named HelloServer
module HelloServer {
// Mount the `web.xtclang.org` library into the module as `web`
package web import web.xtclang.org;
// Mount the `xenia.xtclang.org` library into the module as `xenia`
package xenia import xenia.xtclang.org;
// Import specific classes for web functionality and HTTP handling
import web.*;
import web.http.*;
// The run() method is the entry point for the `HelloServer` module
// It creates a web server instance, configures it, and starts it
void run() {
// Initialize a Xenia web server on localhost with HTTP port 8080 and HTTPS port 8090
xenia.createServer(this, new HostInfo("localhost", 8080, 8090));
// Inject a dependency to console-related features, which print messages to the console
@Inject Console console;
console.print($|To access this server, open a browser on this machine and enter this URL:
|
| http://localhost:8080/
|
| Or:
|
| https://localhost:8090/
|
|Use Ctrl-C to stop.
);
}
// Annotate the `SiteRoot` service indicating this a web service mapped to the root path ("/")
@WebService("/")
service SiteRoot {
// Declare a GET HTTP method, `sayHello`, which returns a string
@Get
String sayHello() = "Hello, World!";
}
}
Compile and run the example by executing xec
from the directory containing a copy of the HelloServer.x
file:
xec HelloServer
You should then see instructions in the terminal with a URL to the locally running server, e.g.:
To access this server, open a browser on this machine and enter this URL:
http://localhost:8080/
Or:
https://localhost:8090/
Use Ctrl-C to stop.
The HelloClient
Module
Now that the web server is up and running, we need to define a client to interact with it. Let's take a look at the example:
https://github.com/xtclang/xvm/blob/master/xdk/src/main/resources/xdk/examples/HelloClient.x
// Define a module named HelloClient
module HelloClient {
// Mount the `web.xtclang.org` library into the module as `web`
package web import web.xtclang.org;
// Inject a dependency to console-related features, which print messages to the console
@Inject Console console;
// Import the HttpClient class for making HTTP requests
import web.HttpClient;
// Define the `HelloClient` entrypoint method that accepts an array of URL strings as arguments
void run(String[] args=["http://localhost:8080"]) {
// Initialize an instance of HttpClient for making HTTP requests
HttpClient client = new HttpClient();
// Extract the URI from the command-line arguments
String uri = args[0];
console.print($"Accessing: {uri.quoted()}");
// Send an HTTP GET request to the specified URI using the get() method of the HttpClient instance
// Convert the server response to a string and assert that the result is not null,
// otherwise, an error message is displayed
assert String result := client.get(uri).to(String) as $"Request to {uri.quoted()} failed";
// Print the response received from the server
console.print($"The server returned: {result}");
}
}
Compile and run the example by executing xec
from the directory containing a copy of the HelloClient.x
file:
xec HelloClient
You should see output in the terminal with the server response, e.g.
Accessing: "http://localhost:8080"
The server returned: Hello, World!
Key Concepts
Let's review some high-level concepts referenced in the example code comments.
Annotations
An annotation is a mixin, which augments the corresponding structure with additional properties or behaviors. In the Ecstasy language, its syntax is @<AnnotationName>
, written above the component it’s applied to. For example:
- The
@WebApp
annotation enables theHelloServer
module to process HTTP requests and return a response. - The
@WebService
annotation enables theSiteRoot
service to declare a set of endpoints for a specific URI path. - The
@Get
annotation determines the HTTP method, and therefore the behavior, of ourHelloWorld
example endpoint.
For more information about Annotations, check out the Understanding Types guide.
Modules
A module is the highest-level organizational unit in Ecstasy. It is the unit of compilation, the unit of versioning and the unit of deployment.
Learn more about Modules in the guide “Structuring your Ecstasy language project with modules”.
Class Keywords
service
, package
and module
are three examples of class keywords, which refer to a set of properties, methods and behaviors for a given class.
For a deep dive into Classes and Class Keywords, take a look at “How to use class keywords in Ecstasy”.
EXPLORE & LEARN
Ready to learn more?
Check out our latest guides, blogs and tutorials!