Skip to content

Commit feee119

Browse files
ViniAbreuMDA2AV
andauthored
Horse is a web framework write in Pascal (#129)
* [pascal] add Horse framework * Update Dockerfile * Add system user for HorseServer Add a system user 'horse' for running the server. * Remove runtime stage from HorseServer Dockerfile * Add nonroot user to HorseServer Dockerfile * Fix HorseServer Docker build (Ubuntu user creation) and Pascal source - Dockerfile: remove Alpine-style `addgroup -S`/`adduser -S` and `USER nonroot`. On the ubuntu:24.04 base `addgroup` is absent, so the build failed with "addgroup: not found" (exit 127); switching user before WORKDIR/COPY/compile would also block writes to /app. Build now runs as root, consistent with the other servers. - HorseServer.lpr: remove the duplicate trailing `end.`. - probe.json: add trailing newline. Verified locally: image builds, container serves HTTP, full probe runs (215 tests). * HorseServer: run as non-root and resolve Docker lint - Run the container as a dedicated non-root `appuser` (`useradd --system`), switching USER only after the FPC compile so build-time writes to /app still succeed. Resolves the SonarCloud hotspot docker:S6471 ("ubuntu image runs as root"). - Sort the apt package list alphanumerically (docker:S7018). - Merge consecutive RUN instructions (docker:S7031): fold git clone + useradd into the apt layer and chmod into the compile layer. Verified locally: image builds, runs as uid 999, serves HTTP, and the full probe passes (215 tests, 0 connection errors, same 76/161 result as before). * all methods for endpoint main * Update HorseServer.lpr --------- Co-authored-by: Diogo Martins <diogoalves@ua.pt>
1 parent 002c3ce commit feee119

4 files changed

Lines changed: 155 additions & 0 deletions

File tree

src/Servers/HorseServer/Dockerfile

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
FROM ubuntu:24.04
2+
ENV DEBIAN_FRONTEND=noninteractive
3+
RUN apt-get update && apt-get install -y --no-install-recommends \
4+
ca-certificates \
5+
fpc \
6+
git \
7+
&& rm -rf /var/lib/apt/lists/* \
8+
&& git clone --depth 1 --branch 3.2.0 https://github.com/HashLoad/horse.git /horse \
9+
&& useradd --system appuser
10+
WORKDIR /app
11+
COPY src/Servers/HorseServer/HorseServer.lpr .
12+
COPY src/Servers/HorseServer/HorseServer.lpi .
13+
RUN mkdir -p /app/out \
14+
&& fpc \
15+
-Mdelphi \
16+
-O2 \
17+
-Fu/horse/src \
18+
-Fu/app \
19+
-FU/app/out \
20+
-o/app/HorseServer \
21+
HorseServer.lpr \
22+
&& chmod +x /app/HorseServer
23+
USER appuser
24+
ENTRYPOINT ["/app/HorseServer"]
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<CONFIG>
3+
<ProjectOptions>
4+
<Version Value="12"/>
5+
<PathDelim Value="\"/>
6+
<General>
7+
<Flags>
8+
<MainUnitHasCreateFormStatements Value="False"/>
9+
<MainUnitHasTitleStatement Value="False"/>
10+
<MainUnitHasScaledStatement Value="False"/>
11+
</Flags>
12+
<SessionStorage Value="InProjectDir"/>
13+
<Title Value="HorseServer"/>
14+
<UseAppBundle Value="False"/>
15+
<ResourceType Value="res"/>
16+
</General>
17+
<BuildModes>
18+
<Item Name="Default" Default="True"/>
19+
</BuildModes>
20+
<PublishOptions>
21+
<Version Value="2"/>
22+
<UseFileFilters Value="True"/>
23+
</PublishOptions>
24+
<RunParams>
25+
<FormatVersion Value="2"/>
26+
</RunParams>
27+
<Units>
28+
<Unit>
29+
<Filename Value="HorseServer.lpr"/>
30+
<IsPartOfProject Value="True"/>
31+
</Unit>
32+
</Units>
33+
</ProjectOptions>
34+
<CompilerOptions>
35+
<Version Value="11"/>
36+
<PathDelim Value="\"/>
37+
<Target>
38+
<Filename Value="HorseServer"/>
39+
</Target>
40+
<SearchPaths>
41+
<IncludeFiles Value="$(ProjOutDir)"/>
42+
<OtherUnitFiles Value="horse\src"/>
43+
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
44+
</SearchPaths>
45+
<Linking>
46+
<Debugging>
47+
<DebugInfoType Value="dsDwarf3"/>
48+
</Debugging>
49+
</Linking>
50+
</CompilerOptions>
51+
<Debugging>
52+
<Exceptions>
53+
<Item>
54+
<Name Value="EAbort"/>
55+
</Item>
56+
<Item>
57+
<Name Value="ECodetoolError"/>
58+
</Item>
59+
<Item>
60+
<Name Value="EFOpenError"/>
61+
</Item>
62+
</Exceptions>
63+
</Debugging>
64+
</CONFIG>
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
program HorseServer;
2+
3+
{$MODE DELPHI}{$H+}
4+
5+
uses
6+
{$IFDEF UNIX}
7+
cthreads,
8+
{$ENDIF}
9+
SysUtils,
10+
Generics.Collections,
11+
Horse,
12+
Horse.Commons;
13+
14+
procedure AllCallBAck(Req: THorseRequest; Res: THorseResponse);
15+
var
16+
LBody: string;
17+
begin
18+
LBody := 'OK';
19+
if Req.MethodType = mtPost then
20+
LBody := Req.Body;
21+
Res.Send(LBody);
22+
end;
23+
24+
procedure EchoCallBack(Req: THorseRequest; Res: THorseResponse);
25+
var
26+
LHeaders: TStringBuilder;
27+
LHeader: TPair<string, string>;
28+
begin
29+
LHeaders := TStringBuilder.Create;
30+
try
31+
for LHeader in Req.Headers.ToArray do
32+
LHeaders.Append(Format('%s: %s%s', [LHeader.Key, LHeader.Value, sLineBreak]));
33+
34+
Res.Send(LHeaders.ToString);
35+
finally
36+
LHeaders.Free;
37+
end;
38+
end;
39+
40+
procedure CookieCallBack(Req: THorseRequest; Res: THorseResponse);
41+
var
42+
LCookies: TStringBuilder;
43+
LCookie: TPair<string, string>;
44+
begin
45+
LCookies := TStringBuilder.Create;
46+
try
47+
for LCookie in Req.Cookie.ToArray do
48+
LCookies.Append(Format('%s=%s%s', [LCookie.Key, LCookie.Value, sLineBreak]));
49+
50+
Res.Send(LCookies.ToString);
51+
finally
52+
LCookies.Free;
53+
end;
54+
end;
55+
56+
begin
57+
THorse.All('/', AllCallBack);
58+
THorse.All('/echo', EchoCallBack);
59+
THorse.All('/cookie', CookieCallBack);
60+
61+
THorse.Listen(8080);
62+
end.

src/Servers/HorseServer/probe.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"name": "Horse",
3+
"language": "Object Pascal (Delphi/FPC)",
4+
"repository": "https://github.com/HashLoad/horse"
5+
}

0 commit comments

Comments
 (0)