FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin for Harbour/xHarbour Small victory: HTTP microservice without any .lib at all
Posts: 6983
Joined: Fri Oct 07, 2005 07:07 PM
Re: Small victory: HTTP microservice without any .lib at all
Posted: Thu Jul 10, 2025 05:48 AM
Hi Lailton,

thanks for your feedback!

Just to check – do I understand your setup correctly?

You're using CGI with Windows IIS, meaning:

The client sends an HTTP request (e.g. via fetch or form)
IIS starts a new process (your .exe application)
Request data is passed via STDIN or environment variables
Your app opens the DBF, performs some logic, returns output via STDOUT
IIS forwards this as the HTTP response
The process terminates

That’s a well-established and efficient setup – especially because IIS handles process creation and termination automatically.

In contrast, my current approach is based on WebSocket, and that brings one key architectural shift:
WebSocket (using Winsock) is part of the Windows operating system itself
it doesn't require Apache, IIS, or any external HTTP server.

The .exe runs persistently as a standalone microservice
It opens a raw TCP socket (socket(), bind(), accept()) via Winsock
Clients communicate directly over WebSocket or fetch (via PHP proxy if needed)
DBF access is handled entirely in-memory
No startup delay – no process fork per request
No .req or .res temp files anymore
This allowed me to reduce the time for updating a single DBF field from ~135 ms to under 35 ms, while also eliminating the race conditions I had during parallel file access.

And just like CGI, the microservice can still start external .exe files if needed:
You can call a report generator
Trigger a background conversion tool
Or even run a Harbour or C program via CreateProcess() or ShellExecute()

So while the microservice is lean and persistent, it can delegate tasks like CGI – with full control over execution and return handling.

I think both models have their strengths.
CGI shines with its tight integration into the server.
WebSocket gives you full control at OS level – and makes it easy to build lightweight, event-driven architectures.

Best regards from Austria,
Otto
Posts: 231
Joined: Fri Jul 20, 2012 01:49 AM
Re: Small victory: HTTP microservice without any .lib at all
Posted: Thu Jul 10, 2025 08:12 PM
Hi Otto,

Interesting your point of view.

:D
Regards,

Lailton Fernando Mariano
Posts: 9
Joined: Tue Nov 12, 2024 01:30 PM
Re: Small victory: HTTP microservice without any .lib at all
Posted: Sun Jul 20, 2025 06:12 AM

Otto,

If you're using a websocket-based microservice approach with Harbour,

I recommend you try "datastar" for the frontend (similar to HTMX + Alpine.js).

It's very interesting.

Regards,

Tom.H.

Posts: 6983
Joined: Fri Oct 07, 2005 07:07 PM
Re: Small victory: HTTP microservice without any .lib at all
Posted: Sun Jul 20, 2025 04:03 PM
Tom, thanks for the suggestion about Datastar!

We’ve already solved that logic ourselves – using pure HTML and JavaScript. With just 2–3 small functions, we cover 90% of what Datastar or HTMX offers – without overhead, without magic, and without any framework baggage.
 
function bindFields(model) {
  document.querySelectorAll("[data-bind]").forEach(el => {
    const key = el.dataset.bind;
    if (el.tagName === "INPUT") {
      el.value = model[key] || "";
      el.addEventListener("input", () => model[key] = el.value);
    } else {
      el.textContent = model[key] || "";
    }
  });
}
Why do we do it this way?

Because debugging stays transparent – no virtual DOM, no reactivity layers.

Because it’s fully HARBOURINO style -compatible – tightly integrated with our JSON-based structure.

And most importantly:
ChatGPT can help you best when you avoid unnecessary abstraction layers.
The more direct your logic, the more precise the feedback – and the faster the result.

That’s why we use no jQuery, no Alpine, no Datastar.
Instead: clarity, structure, control – and real-time understanding.

If you know what you’re doing, you don’t need a 5 kB library to wire a label to a value.
You just need clean thinking – and a reliable assistant who sees exactly what’s going on.

Best regards,
Otto
Posts: 6983
Joined: Fri Oct 07, 2005 07:07 PM
Re: Small victory: HTTP microservice without any .lib at all
Posted: Thu Jul 24, 2025 07:11 AM
Build-In-Formdesigner
Best regards,
Otto
Posts: 6983
Joined: Fri Oct 07, 2005 07:07 PM
Re: Small victory: HTTP microservice without any .lib at all
Posted: Sun Jul 27, 2025 07:17 AM
Harbourino Routing: Clean, Scalable, Patchable

Traditional C-based microservices often rely on long chains of else if (stricmp(...)) blocks to handle routes. This approach quickly becomes messy, error-prone, and hard to extend.

The Harbourino-Style introduces a structured alternative: Routes are defined declaratively via $-> blocks, which the patcher expands into valid C code. GET and POST routes can be separated using clear markers like -> START_IF and -> START_IF_GET.

A simple dummy block (if (0) {}) ensures clean entry into the conditional chain. Adding new routes is straightforward and reduces copy-paste errors. The result is a maintainable, consistent routing tree – ideal for modular microservices.
//-- HARBOURINO HRB_LIBTEST --//

//-- HARBOURINO PATCHBLOCK ROUTING --//
-> START_IF
$-> POST_DELETERECORD : route = deleterecord ; routefunction = HANDLEDELETERECORD
$-> POST_DELETERECORDTEST : route = deleterecordtest ; routefunction = HANDLEDELETERECORDTEST
$-> POST_GETINDEXES : route = getindexes ; routefunction = HANDLEGETINDEXES
$-> POST_GETROUTE : route = getroute ; routefunction = HANDLEGETROUTE
$-> POST_HEARTBEAT : route = heartbeat ; routefunction = HANDLEHEARTBEAT
$-> POST_READDBF : route = readdbf ; routefunction = HANDLEREADDBF
$-> POST_READRECORD : route = readrecord ; routefunction = HANDLEREADRECORD
$-> POST_STATUS_VERSION : route = status ; routefunction = HANDLESTATUSVERSION
$-> POST_UPDATERECORD : route = updaterecord ; routefunction = HANDLEEDITRECORD
$-> POST_UPDATERECORDFIELDS : route = updaterecordfields ; routefunction = HANDLEUPDATERECORD
-> ELSE_END

//-- HARBOURINO GET_ROUTING PATCHBLOCK --//
-> START_IF_GET
$-> GET_SEARCHNAME : route = search?name= ; routefunction = SEARCHNAME
$-> GET_HELLO : route = hello ; routefunction = STATICHELLO
$-> GET_TIME : route = time ; routefunction = STATICTIME
-> ELSE_END_GET

//-- ENDE PATCHBLOCK --//

// Der restliche Sourcecode (Main, Funktionen etc.) bleibt unverändert ↓↓↓

//-- HARBOURINO HB_MAIN --//
REQUEST DBFCDX
REQUEST DBFFPT

STATIC cLog

FUNCTION Main()
   hb_cdpSelect("DEWIN")
   hb_SetTermCP("DEWIN")   // optional

   cLog := time()

   ?  "START Graftonstreet"+ cLog 
   ?  "==================================================" 
   ? cLog

   StartHttpServer()
RETURN NIL

[...]
Posts: 410
Joined: Sun Jan 31, 2010 03:30 PM
Re: Small victory: HTTP microservice without any .lib at all
Posted: Mon Jul 28, 2025 10:00 PM

Lailton,,, buena tarde..

Puedes publicar un pequeño ejemplo de IIS + CGI...

Saludos

JONSSON RUSSI

Posts: 6983
Joined: Fri Oct 07, 2005 07:07 PM
Re: Small victory: HTTP microservice without any .lib at all
Posted: Tue Jul 29, 2025 01:08 AM
From AI

🔍 Structured Comparison: Harbour + CGI vs. Harbour WebSocket/Microservice Server
🧱 1. How does Harbour + CGI work?
🔁 Workflow:
A web server (e.g. IIS or Apache) receives an HTTP request (GET or POST).

The web server calls a CGI program (e.g. myapp.exe).

myapp.exe is started fresh for every request.

It reads environment variables + stdin (for POST) or QUERY_STRING (for GET).

It processes the input and writes output to stdout (usually HTML or JSON).

Then the program terminates.

🛠 Example:

PROCEDURE Main()
LOCAL cQuery := GetEnv("QUERY_STRING")
? "Content-Type: text/plain"
? ""
? "Response to: " + cQuery
RETURN
🧠 2. How does a Harbour Microservice (WebSocket or HTTP Server) work?
🔁 Workflow:
You start a long-running executable (e.g. libtest.exe).

Internally, it opens a socket (e.g. port 8810).

The server waits for incoming requests (e.g. GET /search?name=otto).

A central routing loop parses the request path and calls the correct handler function.

The response is sent directly back via the socket (e.g. JSON).

🛠 Example:

FUNCTION Main()
StartHttpServer() // starts socket loop on port 8810
RETURN NIL

FUNCTION HandleRequest( cPath )
IF cPath == "/search"
RETURN '{"result":"ok"}'
ENDIF
RETURN '{"error":"unknown"}'
⚖️ Comparison: CGI vs Microservice
Aspect Harbour + CGI Harbour Microservice / WebSocket
🔁 Startup New process for every request Runs persistently like a daemon/service
⚙️ Performance Higher overhead (cold start every time) Very fast, no restart between requests
🧠 State management Stateless (no memory or session retention) State possible (e.g. sessions, in-memory cache)
🔌 Integration Works via Apache/IIS using CGI Requires own socket/port (e.g. 8810)
🔐 SSL / Security SSL handled by Apache/IIS SSL must be implemented manually
⚙️ Complexity Simpler, but less flexible More flexible, but requires more coding

🧩 When to Use What?
Purpose / Use Case Recommended Approach
🧾 Simple DBF data query via browser CGI is sufficient
🌐 Integration with classic web server (IIS) CGI is ideal
High-performance or frequent requests Use Microservice
📡 REST API or real-time (WebSocket) services Use Microservice
🧠 Session-based logic / in-memory caching Use Microservice

🚀 Conclusion
CGI is perfect for simple, traditional web requests integrated into existing web servers.

Harbour Microservice (or WebSocket server) is modern, fast, and highly flexible – ideal for APIs, custom dashboards, or real-time integrations.
Posts: 6983
Joined: Fri Oct 07, 2005 07:07 PM
Re: Small victory: HTTP microservice without any .lib at all
Posted: Tue Jul 29, 2025 10:21 AM

Continue the discussion