Skip to main content

Example: Http Server & Client

Example: Http Server

1. Callback function registration

Bind the eid and the callback function name corresponding to its enclave. (this function is designed to deal with the situation where multiple different enclaves are created in a single application. If a single application creates a single enclave, use the reference code in the example)

int main() {
sgx_enclave_id_t eid = 0;
sgx_create_enclave( (const char*)argv[1], 0, nullptr, nullptr, &eid, nullptr );
ok = ssgx::http_u::HttpCallbackManager::GetInstance().RegisterCallbacks(eid, ssgx_ecall_register_enclave_eid, ssgx_ecall_http_on_message);
if(!ok){
printf("Failed to register callback function for HTTP module.\n");
goto _exit;
}

...
}
important

This function is designed to deal with the situation where multiple different enclaves are created in a single application. If a single application creates a single enclave, use the reference code in the example.

2. Handle function implementation in enclave

void HandleHello(Request& request, Response& response) {
std::string info;
request.ToJsonStr(info);
std::string name = request.GetParamValue("name"); // Extract `name` from query parameters

if (name.empty()) {
name = "World"; // Default value if `name` is not provided
}

std::string reply;
reply = "Hello " + name + "!";

response.SetResp(reply, "text/plain", 200);
}

3. Bind the Handle function to the method and path, then start the server

Server srv;
std::string url = "http://0.0.0.0:83";
srv.Listen(url);
srv.Get("/hello", [](auto& req, auto& resp) { HandleHello(req, resp); });
srv.Start();
while (1) {
ssgx::utils_t::sleep(10);
}

4. Filter component (Optional)

We also provide the filter component, which only needs to be added before the server is started.

  • Implementing your own filter
class TimingFilter : public ssgx::http_t::Filter {
struct Context{
int64_t start_time;
};

public:
bool Before(ssgx::http_t::Request& request, ssgx::http_t::Response& response) override {
Context ctx{};
ctx.start_time = ssgx::utils_t::PreciseTime::NowInMilliseconds();
request.SetAttribute("TimingFilterCtx", ctx);
return true;
}

void After(ssgx::http_t::Request& request, ssgx::http_t::Response& response) override {
if(request.HasAttribute<Context>("TimingFilterCtx")){
Context& ctx = request.GetAttribute<Context>("TimingFilterCtx");
auto end_time = ssgx::utils_t::PreciseTime::NowInMilliseconds();
auto duration = end_time - ctx.start_time;
std::string log_message = "[TimingFilter] " + request.Method() + " " + request.Path();
log_message += "\n - Processed in " + std::to_string(duration) + " milliseconds";

SSGX_LOG(INFO) << log_message;
}
}
};
  • Add filter to server before the server is started.
Server srv;
std::string url = "http://0.0.0.0:83";
srv.Listen(url);
srv.Get("/hello", [](auto& req, auto& resp) { HandleHello(req, resp); });
srv.AddFilter(std::make_unique<TimingFilter>());
srv.Start();

Example: Http Client

Send an HTTP request directly in enclave. The client supports TLS.

  • Http Request
std::string path = "/hello";
Client client = Client("http://0.0.0.0:83");
Headers headers = {
{"Content-Type", "text/plain"}
};
ssgx::http_t::Result result = client.Get(path, headers, 5);
ssgx::utils_t::Printf("result body=%s\n", result->body().c_str());
  • Https Request
const char* binance_host = "https://api1.binance.com";
const int binance_port = 443;
const char* binance_account_path = "/api/v3/account";
const char* binance_ca = "-----BEGIN CERTIFICATE-----\n"
"MIIEjTCCA3WgAwIBAgIQDQd4KhM/xvmlcpbhMf/ReTANBgkqhkiG9w0BAQsFADBh\n"
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH\n"
"MjAeFw0xNzExMDIxMjIzMzdaFw0yNzExMDIxMjIzMzdaMGAxCzAJBgNVBAYTAlVT\n"
"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n"
"b20xHzAdBgNVBAMTFkdlb1RydXN0IFRMUyBSU0EgQ0EgRzEwggEiMA0GCSqGSIb3\n"
"DQEBAQUAA4IBDwAwggEKAoIBAQC+F+jsvikKy/65LWEx/TMkCDIuWegh1Ngwvm4Q\n"
"yISgP7oU5d79eoySG3vOhC3w/3jEMuipoH1fBtp7m0tTpsYbAhch4XA7rfuD6whU\n"
"gajeErLVxoiWMPkC/DnUvbgi74BJmdBiuGHQSd7LwsuXpTEGG9fYXcbTVN5SATYq\n"
"DfbexbYxTMwVJWoVb6lrBEgM3gBBqiiAiy800xu1Nq07JdCIQkBsNpFtZbIZhsDS\n"
"fzlGWP4wEmBQ3O67c+ZXkFr2DcrXBEtHam80Gp2SNhou2U5U7UesDL/xgLK6/0d7\n"
"6TnEVMSUVJkZ8VeZr+IUIlvoLrtjLbqugb0T3OYXW+CQU0kBAgMBAAGjggFAMIIB\n"
"PDAdBgNVHQ4EFgQUlE/UXYvkpOKmgP792PkA76O+AlcwHwYDVR0jBBgwFoAUTiJU\n"
"IBiV5uNu5g/6+rkS7QYXjzkwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsG\n"
"AQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEAMDQGCCsGAQUFBwEB\n"
"BCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEIGA1Ud\n"
"HwQ7MDkwN6A1oDOGMWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEds\n"
"b2JhbFJvb3RHMi5jcmwwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEW\n"
"HGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwDQYJKoZIhvcNAQELBQADggEB\n"
"AIIcBDqC6cWpyGUSXAjjAcYwsK4iiGF7KweG97i1RJz1kwZhRoo6orU1JtBYnjzB\n"
"c4+/sXmnHJk3mlPyL1xuIAt9sMeC7+vreRIF5wFBC0MCN5sbHwhNN1JzKbifNeP5\n"
"ozpZdQFmkCo+neBiKR6HqIA+LMTMCMMuv2khGGuPHmtDze4GmEGZtYLyF8EQpa5Y\n"
"jPuV6k2Cr/N3XxFpT3hRpt/3usU/Zb9wfKPtWpoznZ4/44c1p9rzFcZYrWkj3A+7\n"
"TNBJE0GmP2fhXhP1D/XVfIW/h0yCJGEiV9Glm/uGOa3DXHlmbAcxSyCRraG+ZBkA\n"
"7h4SeM6Y8l/7MBRpPCz6l8Y=\n"
"-----END CERTIFICATE-----\n"
"-----BEGIN CERTIFICATE-----\n"
"MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh\n"
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH\n"
"MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT\n"
"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n"
"b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG\n"
"9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI\n"
"2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx\n"
"1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ\n"
"q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz\n"
"tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ\n"
"vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP\n"
"BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV\n"
"5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY\n"
"1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4\n"
"NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG\n"
"Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91\n"
"8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe\n"
"pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl\n"
"MrY=\n"
"-----END CERTIFICATE-----";

ssgx::http_t::TypeHeaders headers = {{"X-MBX-APIKEY", "{Your-API-Key}"}};
ssgx::http_t::TypeParams params = {{"omitZeroBalances", "true"},
{"recvWindow", "60000"},
{"timestamp", "1731565108329"},
{"signature", "65cfe3fb183daf8937a881f646e03c3d03a4be7ed4600011b8ce36d59a3f2535"}};

ssgx::http_t::Client http(binance_host, binance_port, binance_ca);
if (auto result = http.Get(binance_account_path, headers, params)) {
ssgx::utils_t::Printf("%d\n", result->status_code());
ssgx::utils_t::Printf("%s\n\n", result->Body().c_str());
} else {
ssgx::utils_t::Printf("\nFailed to call GET method! error: %s, internal error: %s\n",
result.error().message().c_str(), result.error().internal_error().c_str());
}
important

We have built-in some CA root certificates exported from Google Chrome, so you don't need to enter the CA root certificate yourself when requesting most websites.