Skip to content

Instantly share code, notes, and snippets.

@PixlRainbow
Last active December 4, 2019 10:12
Show Gist options
  • Save PixlRainbow/b720c965dde920cc404095848942ad02 to your computer and use it in GitHub Desktop.
Save PixlRainbow/b720c965dde920cc404095848942ad02 to your computer and use it in GitHub Desktop.
SSE using cpp-httplib
#include <httplib.h>
#include <cstdio>
#include <chrono>
using namespace httplib;
bool reconnect = true;
unsigned long retry = 3000;
//warning: events do not necessarily correspond with chunks
//a chunk may contain more than one event
bool chunk_callback(const char *data, uint64_t len){
//warning: this callback runs async
std::string msg(data, len);
if(msg.rfind("retry: ", 8) == 0){
retry = std::stoul(msg.substr(7));
printf("detected timeout: %lu\n", retry);
};
printf("new chonk: %s\n", msg.c_str());
return true;
});
int main(){
// http://samshull.com/server-sent/events.php
Client cli("samshull.com");
cli.follow_location(true);
const httplib::Headers headers = {
{ "Accept", "text/event-stream" },
{ "Connection", "Keep-Alive"}
};
while(reconnect){
auto res = cli.Get("/server-sent/events.php", headers, chunk_callback);
if(res){
printf("HTTP %i\n", res->status);
//check that response code is 2xx
reconnect = (res->status / 100) == 2;
}
else{
printf("SSE stream ended. Will retry in %f seconds\n", retry/1000.0);
std::this_thread::sleep_for(std::chrono::milliseconds(retry));
printf("Retrying\n");
}
}
printf("closed connection\n");
return 0;
}
#include <chrono>
#include <cstdio>
#include <httplib.h>
using namespace httplib;
uint64_t event_id;
void create_event(uint64_t offset, DataSink sink, Done done){
std::string eventdata;
std::this_thread::sleep_for(std::chrono::seconds(3));
if(event_id == 0)
//tell client to retry in 15s if disconnected
eventdata = "retry: 15000\n\n";
else
{
eventdata += "id: ";
eventdata += std::to_string(event_id);
eventdata += "\ndata: This is an event message\n\n";
}
event_id++;
sink(eventdata.c_str(), eventdata.length());
}
int main(void) {
Server svr;
svr.Get("/eventsrc",[](const Request &req, Response &res){
res.set_chunked_content_provider(create_event);
res.set_header("Content-Type", "text/event-stream");
});
svr.listen("localhost", 8080);
return 0;
}
@kreativnix
Copy link

Unfortunately your program can not compile:
error: ‘struct httplib::Response’ has no member named ‘content_producer’
res.content_producer = create_event;
I have the newest httplib.h!
Gerald

@PixlRainbow
Copy link
Author

@kreativnix sorry! yhirose updated httplib.h upstream and changed the content streaming interface on the server side. I have edited this gist to reflect his changes.

@kreativnix
Copy link

Hi PixlRainbow, I thank you very much for the quick reaction. I did not believe that in advance. Now I can continue to test.
My goal is to find a relative simple possibility to program in a RasPi 3B+ a program including webserver functionality with SSE, because I have measurment data to display. Maybe this httplib will help!
Many thanks and a nice weekend
Gerald

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment