Skip to content

Commit

Permalink
feat(examples): add a very WIP, basic http client example
Browse files Browse the repository at this point in the history
  • Loading branch information
BradleyChatha committed Dec 23, 2023
1 parent d5cecbf commit 7ea76f3
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 1 deletion.
64 changes: 64 additions & 0 deletions examples/http-client-curl/main.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Purpose: This is a simple command line tool that uses the higher-level HttpClient stuff
// to send out a simple HTTP request and print the response to stdout.
//
// Additionally this example is showing a more GC-friendly way of using Juptune.

import core.time;
import juptune.core.ds, juptune.core.util, juptune.event, juptune.http;

__gshared string[] g_args;
__gshared int g_statusCode;

int main(string[] args)
{
g_args = args;

auto loop = EventLoop(EventLoopConfig());
loop.addGCThread(() nothrow {
try curl();
catch(Exception ex)
{
import std.stdio : stderr;
import std.exception : assumeWontThrow;

stderr.writeln(ex).assumeWontThrow;
g_statusCode = 1;
}
});
loop.join();

return g_statusCode;
}

void curl()
{
// CLI interface is super raw because this is just a barebones example right now.
// I want to make this a lot more elaborate in the future.
IpAddress address;
IpAddress.parse(address, g_args[1], 80).throwIfError;

scope client = HttpClient(HttpClientConfig());
client.connect(address).throwIfError;

scope request = HttpRequest();
request.withMethod("GET");
request.withPath("/");
request.setHeader("Connection", "close");

scope HttpResponse response;
client.request(request, response).throwIfError;

// Print the response to stdout.
import std.stdio : writefln;

writefln("%s %s", response.status, response.reason[]);
foreach(ref header; response.headers[])
writefln("%s: %s", header.name[], header.value[]);
writefln("\n%s", cast(char[])response.body[]);
}

void throwIfError(Result result)
{
if(result.isError)
throw new Exception(result.error);
}
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ juptune_all_dep = declare_dependency(
examples = {
'http-hello-world-hardcoded': ['./examples/http-hello-world-hardcoded/main.d'],
'http-echo-low-level': ['./examples/http-echo-low-level/main.d'],
'http-client-curl': ['./examples/http-client-curl/main.d'],
}

foreach example_name, example_srcs : examples
Expand Down
9 changes: 8 additions & 1 deletion src/juptune/http/client.d
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ struct HttpClient
+
+ Please note that the `HttpResponse` does not contain a body - it only contains the headers and status line.
+
+ Please note that this is marked `@safe`` to help make it clear that the `scope` for `bodyChunk` is
+ Please note that this is marked `@safe` to help make it clear that the `scope` for `bodyChunk` is
+ _very_ important to adhear to.
+
+ You can (and probably will have to) mark your func/lambda as `@trusted`,
Expand Down Expand Up @@ -246,6 +246,13 @@ struct HttpClient
Result connect(IpAddress ip) @nogc nothrow
in(!this._isConnected, "This client is already connected")
{
if(!this._socket.isOpen)
{
auto result = this._socket.open();
if(result.isError)
return result;
}

auto result = this._socket.connect(ip);
if(result.isError)
return result;
Expand Down

0 comments on commit 7ea76f3

Please sign in to comment.