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.