From ced4156cc9b455dce3364182f4d5822adfe1976b Mon Sep 17 00:00:00 2001 From: andrewlalis Date: Tue, 26 Sep 2023 11:02:37 -0400 Subject: [PATCH] Added new article. --- articles.html | 15 +++ articles/api-with-handy-httpd.html | 150 +++++++++++++++++++++++++++++ styles/article.css | 4 - 3 files changed, 165 insertions(+), 4 deletions(-) create mode 100644 articles/api-with-handy-httpd.html diff --git a/articles.html b/articles.html index bf873c2..d5e0680 100644 --- a/articles.html +++ b/articles.html @@ -47,7 +47,22 @@

+ + +
+ +

Creating an API with Handy-Httpd

+
+ + D Lang + Showcase + Tutorial +
+

+ Take a look at how you can set up a web API with my Handy-Httpd library. +

+

A Beginner's Guide to Searching with Lucene

diff --git a/articles/api-with-handy-httpd.html b/articles/api-with-handy-httpd.html new file mode 100644 index 0000000..e1f3a74 --- /dev/null +++ b/articles/api-with-handy-httpd.html @@ -0,0 +1,150 @@ + + + + + Creating an API with Handy-Httpd + + + + + + + + + + + + + + + + +
+
+

Creating an API with Handy-Httpd

+

+ Written on , by Andrew Lalis. +

+
+
+

Introduction

+

+ When I started programming in the D language, I was coming fresh from the world of Java and Spring, where setting up a new web API for a project was pretty much as simple as creating a new method annotated with @GetMapping. In the D world, the closest thing to an all-encompassing web framework is Vibe.d, which is quite convoluted (from a beginner's perspective), and is heavily focused on its own ecosystem and async implementations. That gives it a sort of "walled-garden" feel. There were other, smaller HTTP web server libraries, but none were well documented. So in the end, I set out to build my own HTTP server, which then evolved into more of an HTTP web framework. That's Handy-Httpd. +

+

+ Handy-Httpd was built on the concept of an HttpRequestHandler, a single unit that takes an HTTP request and does stuff with it. +

+
+

+				class ExampleHandler : HttpRequestHandler {
+					void handle(ref HttpRequestContext ctx) {
+						ctx.response.writeBodyString("Hello world!");
+					}
+				}
+			
+
Here's an example of an HttpRequestHandler that just responds with "Hello world!" to any request.
+
+

+ With this request handler, and the principle of composition, we can build up a complete web framework from a few well-purposed handlers. +

+
+ +
+

Setting Up

+

+ As with any web server, there's some startup and configuration that needs to be done to get everything working, so we'll get that out of the way first. +

+

+ We need to create a new D project, and add handy-httpd as a dependency. Do so with the dub CLI tool, or however you prefer to create D projects. Then we'll set up the basic HTTP server in our project's main file. +

+
+

+				import handy_httpd;
+				import handy_httpd.handlers.path_delegating_handler;
+
+				void main() {
+					ServerConfig config = ServerConfig.defaultValues();
+					config.workerPoolSize = 3;
+					PathDelegatingHandler pathHandler = new PathDelegatingHandler();
+					// TODO: Add mappings to pathHandler
+					HttpServer server = new HttpServer(pathHandler, config);
+					server.start();
+				}
+			
+
+

The typical boilerplate consists of three main things:

+
    +
  1. Configuration
  2. +
  3. Building our request handler
  4. +
  5. Starting the server
  6. +
+

+ For illustrations' sake, I've configured this server to use 3 workers in its pool for handling requests. You might need more depending on your traffic. I've also created a new PathDelegatingHandler which will serve as the basis for the API's set of endpoints. Check out the documentation on this handler for a detailed explanation of what it can do; in short, we can register new API endpoints to it. +

+
+
+

Adding an Endpoint

+

+ Now that our server is set up, all we need to do is define some endpoints for users to interact with. This is as simple as creating an HttpRequestHandler and registering it with our pathHandler that we defined on line 7. +

+

+ To keep things simple to start, we'll add a status endpoint that just returns the string "online". For something this basic, there's no need to create a whole new class; instead, we'll just define a function. +

+
+

+				void handleStatus(ref HttpRequestContext ctx) {
+					ctx.response.writeBodyString("online");
+				}
+			
+
+

+ And then, we'll register it with our path handler so that GET requests to /status will be directed to the handleStatus function. +

+
+

+				pathHandler.addMapping(Method.GET, "/status", &handleStatus);
+			
+
+

+ Done! We can now run our project and navigate to localhost:8080/status, and we should see the text "online". It's that simple. +

+
+
+

Posting Data to Our API

+

+ A GET endpoint is easy enough, but making an endpoint that accepts the user's data isn't too hard either. +

+
+

+				void receivePost(ref HttpRequestContext ctx) {
+					JSONValue content = ctx.request.readBodyAsJson();
+					// Do stuff with the content.
+				}
+			
+
+
+ + Back to Articles +
+ + + diff --git a/styles/article.css b/styles/article.css index 68bc04d..483328f 100644 --- a/styles/article.css +++ b/styles/article.css @@ -19,7 +19,3 @@ figure { code { color: var(--code-color); } - -pre { - padding: 0.25em !important; -}