[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Help with a unikernel webserver


  • To: "Belej, Miroslav" <belejmir@xxxxxxxxxxx>, "mirageos-devel@xxxxxxxxxxxxxxxxxxxx" <mirageos-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: Hannes Mehnert <hannes@xxxxxxxxxxx>
  • Date: Mon, 5 May 2025 09:27:36 +0200
  • Autocrypt: addr=hannes@xxxxxxxxxxx; keydata= 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
  • Delivery-date: Mon, 05 May 2025 07:27:53 +0000
  • List-id: Developer list for MirageOS <mirageos-devel.lists.xenproject.org>

Dear Miroslav,


thanks for reaching out.

So, your config.ml:
> open Mirage
> let stack = generic_stackv4v6 default_network
>
> let net = netif “secret”
> let secret_stack = generic_stackv4v6 net
> (* Main unikernel module *)
> let main =
>          main
>          ~packages:[package "cohttp-mirage"]
>          "Unikernel.Main"
>          (pclock @-> conduit @-> resolver @-> stackv4v6 @-> job)
>
> let () =
> register "frontend-server" [ main $ default_posix_clock $ conduit_direct stack $ resolver_dns stack $ stack ]

Here, you'll need to use & provide the "secret_stack":

let main =
         main
         ~packages:[package "cohttp-mirage"]
         "Unikernel.Main"
(pclock @-> conduit @-> conduit @-> resolver @-> stackv4v6 @-> job)

let () =
register "frontend-server" [ main $ default_posix_clock $ conduit_direct stack $ conduit_direct secret_stack $ resolver_dns secret_stack $ stack ]


Which will then result in your unikernel being a bit modified:
> module Main
>          (Pclock : Mirage_clock.PCLOCK)
>          (Conduit : Conduit_mirage.S)
>          (Resolver : Resolver_mirage.S)
>          (Stack : Tcpip.Stack.V4V6) = struct
>
>    module Client = Cohttp_mirage.Client.Make(Pclock)(Resolver)(Conduit)
>    module Server = Cohttp_mirage.Server.Make(Conduit)

will now be:

module Main
         (Pclock : Mirage_clock.PCLOCK)
         (Conduit : Conduit_mirage.S)
         (Secret_conduit : Conduit_mirage.S)
         (Secret_resolver : Resolver_mirage.S)
         (Stack : Tcpip.Stack.V4V6) = struct

module Client = Cohttp_mirage.Client.Make(Pclock)(Secret_resolver)(Secret_conduit)
   module Server = Cohttp_mirage.Server.Make(Conduit)


And then, also your "start" function is slightly adapted:
>    let start _pclock _conduit _resolver stack =

will be:
   let start _pclock _conduit _secret_conduit _secret_resolver stack =


And then your HTTP client will use the secret network stack, while the server uses the default one.

Hope this helps,

Hannes


On 01/05/2025 22:58, Belej, Miroslav wrote:
Hi, I am developing a unikernel webserver for my thesis and I would be glad for 
help, as I am not really good with OCaml. I already have a running and 
functional webserver, which acts as proxy between user and backend. Right now, 
it uses the same tcp/ip stack for both the user and for forwarding and 
receiving request from backend. I need to have separate stack for both of them. 
I am using Cohttp_mirage library. Here is the code for the unikernel I 
currently have :
open Lwt.Infix


let target_host = "http://192.168.254.11";
let target_port = 8081

module Main
         (Pclock : Mirage_clock.PCLOCK)
         (Conduit : Conduit_mirage.S)
         (Resolver : Resolver_mirage.S)
         (Stack : Tcpip.Stack.V4V6) = struct

   module Client = Cohttp_mirage.Client.Make(Pclock)(Resolver)(Conduit)
   module Server = Cohttp_mirage.Server.Make(Conduit)
   (*Define the forwarding logic*)
   let forward_request uri body resolver conduit =
     let target_uri = Uri.of_string target_host in
     let target_uri = Uri.with_port target_uri (Some target_port) in
     let target_uri = Uri.with_path target_uri (Uri.path uri ) in
     Logs.info (fun f -> f "Forwarding to %s" (Uri.to_string target_uri));
     let headers = Cohttp.Header.init () in
     let body = Cohttp_lwt.Body.of_string body in

     let ctx = Client.ctx resolver conduit in

     Client.post ~ctx ~headers ~body target_uri >>= fun (resp, resp_body) ->
     Cohttp_lwt.Body.to_string resp_body >|= fun body_str ->
     Logs.info (fun f -> f "Received response from %s" (Uri.to_string 
target_uri));
     (resp, body_str)


   (* Define the HTTP server callback *)
   let server_callback _conn req body resolver conduit =
     let uri = Cohttp.Request.uri req in
     let method_ = Cohttp.Request.meth req in
     Logs.info (fun f ->
             f "Received %s request for %s"
             (Cohttp.Code.string_of_method method_)
             (Uri.to_string uri));
     Cohttp_lwt.Body.to_string body >>= fun body_str ->
     let response_body = "This will be hashed-> " ^ body_str in
     Logs.info (fun f -> f "Response Body: %s" response_body);
     forward_request uri body_str resolver conduit >>= fun (response, 
response_body) ->
     Logs.info (fun f -> f "Response body from forwarded request: %s" 
response_body);
     Lwt.return (response, Cohttp_lwt.Body.of_string response_body)


     (* Start the HTTP server *)
   let start _pclock _conduit _resolver stack =
     Logs.info (fun f -> f "Before port");
     let port = 8080 in
     Logs.info (fun f -> f "Defined port");
     Logs.info (fun f -> f "Starting MirageOS HTTP server on port %d" port);
     let callback _conn req body = server_callback _conn req body _resolver 
_conduit in
     let mode : Conduit_mirage.server = `TCP port in
     let server = Server.make ~callback () in

     Server.listen stack mode server
end

with config.ml :

open Mirage
let stack = generic_stackv4v6 default_network

let net = netif “secret”
let secret_stack = generic_stackv4v6 net
(* Main unikernel module *)
let main =
         main
         ~packages:[package "cohttp-mirage"]
         "Unikernel.Main"
         (pclock @-> conduit @-> resolver @-> stackv4v6 @-> job)

let () =
   register "frontend-server" [ main $ default_posix_clock $ conduit_direct 
stack $ resolver_dns stack $ stack ]

So I would like to use the secret_stack for communicating with the backend. I 
am thankful for any response.




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.