Handle HTTP requests
One of the key steps in creating a service is managing HTTP requests, as they serve as the primary means for users to interact with the system.
If you followed the guide about creating an HMI service, you already have an HTTP server up running, serving an application on a specific port.
Overview
The process of handling each request is straightforward. While the implementation details may vary between programming languages, the core steps remain consistent:
- Validate user provided URL
- Execute the action attached to that endpoint, for example [ listOperations ]
- Write the response to the request object, including both headers and data.
Example HTTP handle
In the previous section you created an HTTP server with the following command:
if err := http.ListenAndServe(portAddress, nil); err != nil {
log.Fatalf("Failed to start HTTP server: %v", err)
}
Now let's say you want to provide an endpoint for the user to list all available operations. You could do so by creating a custom HTTP handler. To achieve this, we can begin by defining a simple function that handles serving index.html and any static files, while also ensuring that valid endpoint calls are properly identified.
serveFunc := func(response http.ResponseWriter, request *http.Request) {
// Handle the request to '/' to avoid the server handling
// all request even for static files in index.html
if request.URL.Path == "/" || request.URL.Path == "/index.html" {
log.Printf("Serving index.html")
serveIndexFile(response, request, indexTemplate, baseURL)
return
}
// Handle valid endpoints
switch request.URL.Path {
case "/api/executive/operations":
// execute the action the endpoint should perform
listOperations(response, request, executiveClient)
return
case "another/valid/endpoint":
// yoursEndpointAction(response, request, solutionClient)
return
}
// Handling static files
// For example the ones in index.html
f, err := http.Dir(path.Join(filesRoot, frontendDir)).Open(request.URL.Path)
if err != nil {
http.NotFound(response, request)
return
}
defer f.Close()
http.ServeFile(response, request, path.Join(filesURL, request.URL.Path))
}
Find a snippet to listOperations function as well as the serveIndexFile code in the sdk-examples repo.
Now we create an HTTP handler from this function
handler := http.Handler(http.HandlerFunc(serveFunc))
And finally we can launch the HTTP server using this custom handler
if err := http.ListenAndServe(portAddress, handler); err != nil {
log.Fatalf("Failed to start HTTP server: %v", err)
}
This approach sets up an HTTP server that provides various endpoints, allowing developers to quickly add a wide range of functionalities. They can leverage the full suite of Flowstate tools or create custom functionalities using gRPC for direct interaction with the solution.
Next steps
The full source code for this example is available in the intrinsic-ai/sdk-examples repository.