Http Server in Ada
Here’s the translation of the HTTP server example from Go to Ada, formatted in Markdown suitable for Hugo:
Our HTTP server example demonstrates how to create a basic web server using Ada. We’ll use the GNAT implementation of Ada, which provides the GNAT.Sockets
package for network programming.
with Ada.Text_IO;
with GNAT.Sockets;
with Ada.Strings.Unbounded;
with Ada.Containers.Indefinite_Hashed_Maps;
with Ada.Strings.Hash;
procedure HTTP_Server is
use Ada.Text_IO;
use GNAT.Sockets;
use Ada.Strings.Unbounded;
package String_Maps is new Ada.Containers.Indefinite_Hashed_Maps
(Key_Type => String,
Element_Type => Unbounded_String,
Hash => Ada.Strings.Hash,
Equivalent_Keys => "=");
procedure Hello (Socket : Socket_Type) is
begin
String'Write (Stream (Socket), "HTTP/1.1 200 OK" & ASCII.CR & ASCII.LF);
String'Write (Stream (Socket), "Content-Type: text/plain" & ASCII.CR & ASCII.LF);
String'Write (Stream (Socket), "" & ASCII.CR & ASCII.LF);
String'Write (Stream (Socket), "hello" & ASCII.LF);
end Hello;
procedure Headers (Socket : Socket_Type; Request : String) is
Headers : String_Maps.Map;
Start : Positive := Request'First;
End_Pos : Natural;
begin
-- Parse headers (simplified)
while Start < Request'Last loop
End_Pos := Ada.Strings.Fixed.Index (Request (Start .. Request'Last), ASCII.LF & "");
if End_Pos = 0 then
End_Pos := Request'Last;
else
End_Pos := End_Pos - 1;
end if;
declare
Line : constant String := Request (Start .. End_Pos);
Colon : constant Natural := Ada.Strings.Fixed.Index (Line, ":");
begin
if Colon /= 0 then
Headers.Insert (Line (Line'First .. Colon - 1),
To_Unbounded_String (Line (Colon + 2 .. Line'Last)));
end if;
end;
Start := End_Pos + 2;
end loop;
-- Write response
String'Write (Stream (Socket), "HTTP/1.1 200 OK" & ASCII.CR & ASCII.LF);
String'Write (Stream (Socket), "Content-Type: text/plain" & ASCII.CR & ASCII.LF);
String'Write (Stream (Socket), "" & ASCII.CR & ASCII.LF);
-- Echo headers
for C in Headers.Iterate loop
String'Write (Stream (Socket),
String_Maps.Key (C) & ": " & To_String (String_Maps.Element (C)) & ASCII.LF);
end loop;
end Headers;
Server_Socket : Socket_Type;
Client_Socket : Socket_Type;
Address : Sock_Addr_Type;
Request : String (1 .. 1024);
Last : Natural;
begin
Address.Addr := Inet_Addr ("127.0.0.1");
Address.Port := 8090;
Create_Socket (Server_Socket);
Set_Socket_Option (Server_Socket, Socket_Level, (Reuse_Address, True));
Bind_Socket (Server_Socket, Address);
Listen_Socket (Server_Socket);
Put_Line ("Server started on port 8090");
loop
Accept_Socket (Server_Socket, Client_Socket, Address);
String'Read (Stream (Client_Socket), Request, Last);
if Ada.Strings.Fixed.Index (Request (1 .. Last), "/hello") /= 0 then
Hello (Client_Socket);
elsif Ada.Strings.Fixed.Index (Request (1 .. Last), "/headers") /= 0 then
Headers (Client_Socket, Request (1 .. Last));
else
String'Write (Stream (Client_Socket), "HTTP/1.1 404 Not Found" & ASCII.CR & ASCII.LF);
end if;
Close_Socket (Client_Socket);
end loop;
end HTTP_Server;
This Ada program creates a basic HTTP server that listens on port 8090. It defines two routes: “/hello” and “/headers”.
The Hello
procedure is a simple handler that responds with “hello”.
The Headers
procedure is more sophisticated. It parses the incoming HTTP headers and echoes them back in the response.
In the main procedure, we set up a server socket, bind it to the local address and port 8090, and then enter an infinite loop to accept incoming connections.
For each connection, we read the request, determine which handler to call based on the requested path, and then close the client socket.
To run the server:
- Save the code in a file named
http_server.adb
. - Compile the code:
$ gnatmake http_server.adb
- Run the server:
$ ./http_server
Server started on port 8090
You can then access the server using curl or a web browser:
$ curl localhost:8090/hello
hello
This example demonstrates basic socket programming and HTTP handling in Ada. Note that for a production server, you’d want to add error handling, implement proper HTTP parsing, and possibly use a more robust web framework.