Skip to content

Commit 2e360f9

Browse files
committed
Improved Stream interface
1 parent e5ca863 commit 2e360f9

File tree

13 files changed

+201
-53
lines changed

13 files changed

+201
-53
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ example/hello
66
example/simplesvr
77
example/benchmark
88
example/redirect
9+
example/sse
910
example/upload
1011
example/*.pem
1112
test/test

example/Makefile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ OPENSSL_DIR = /usr/local/opt/openssl
55
OPENSSL_SUPPORT = -DCPPHTTPLIB_OPENSSL_SUPPORT -I$(OPENSSL_DIR)/include -L$(OPENSSL_DIR)/lib -lssl -lcrypto
66
ZLIB_SUPPORT = -DCPPHTTPLIB_ZLIB_SUPPORT -lz
77

8-
all: server client hello simplesvr upload redirect benchmark
8+
all: server client hello simplesvr upload redirect sse benchmark
99

1010
server : server.cc ../httplib.h Makefile
1111
$(CXX) -o server $(CXXFLAGS) server.cc $(OPENSSL_SUPPORT) $(ZLIB_SUPPORT)
@@ -25,6 +25,9 @@ upload : upload.cc ../httplib.h Makefile
2525
redirect : redirect.cc ../httplib.h Makefile
2626
$(CXX) -o redirect $(CXXFLAGS) redirect.cc $(OPENSSL_SUPPORT) $(ZLIB_SUPPORT)
2727

28+
sse : sse.cc ../httplib.h Makefile
29+
$(CXX) -o sse $(CXXFLAGS) sse.cc $(OPENSSL_SUPPORT) $(ZLIB_SUPPORT)
30+
2831
benchmark : benchmark.cc ../httplib.h Makefile
2932
$(CXX) -o benchmark $(CXXFLAGS) benchmark.cc $(OPENSSL_SUPPORT) $(ZLIB_SUPPORT)
3033

@@ -33,4 +36,4 @@ pem:
3336
openssl req -new -key key.pem | openssl x509 -days 3650 -req -signkey key.pem > cert.pem
3437

3538
clean:
36-
rm server client hello simplesvr upload redirect benchmark *.pem
39+
rm server client hello simplesvr upload redirect sse benchmark *.pem

example/sse.cc

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
//
2+
// sse.cc
3+
//
4+
// Copyright (c) 2020 Yuji Hirose. All rights reserved.
5+
// MIT License
6+
//
7+
8+
#include <atomic>
9+
#include <chrono>
10+
#include <condition_variable>
11+
#include <httplib.h>
12+
#include <iostream>
13+
#include <mutex>
14+
#include <thread>
15+
16+
using namespace httplib;
17+
using namespace std;
18+
19+
class EventDispatcher {
20+
public:
21+
EventDispatcher() {
22+
id_ = 0;
23+
cid_ = -1;
24+
}
25+
26+
void add_sink(DataSink *sink) {
27+
unique_lock<mutex> lk(m_);
28+
int id = id_;
29+
cv_.wait(lk, [&] { return cid_ == id; });
30+
if (sink->is_writable()) { sink->write(message_.data(), message_.size()); }
31+
}
32+
33+
void send_event(const string &message) {
34+
lock_guard<mutex> lk(m_);
35+
cid_ = id_++;
36+
message_ = message;
37+
cv_.notify_all();
38+
}
39+
40+
private:
41+
mutex m_;
42+
condition_variable cv_;
43+
atomic_int id_;
44+
atomic_int cid_;
45+
string message_;
46+
};
47+
48+
const auto html = R"(
49+
<!DOCTYPE html>
50+
<html lang="en">
51+
<head>
52+
<meta charset="UTF-8">
53+
<title>SSE demo</title>
54+
</head>
55+
<body>
56+
<script>
57+
const ev1 = new EventSource("event1");
58+
ev1.onmessage = function(e) {
59+
console.log('ev1', e.data);
60+
}
61+
const ev2 = new EventSource("event2");
62+
ev2.onmessage = function(e) {
63+
console.log('ev2', e.data);
64+
}
65+
</script>
66+
</body>
67+
</html>
68+
)";
69+
70+
int main(void) {
71+
EventDispatcher ed;
72+
73+
Server svr;
74+
75+
svr.Get("/", [&](const Request & /*req*/, Response &res) {
76+
res.set_content(html, "text/html");
77+
});
78+
79+
svr.Get("/event1", [&](const Request & /*req*/, Response &res) {
80+
cout << "connected to event1..." << endl;
81+
res.set_header("Content-Type", "text/event-stream");
82+
res.set_chunked_content_provider(
83+
[&](uint64_t /*offset*/, DataSink &sink) { ed.add_sink(&sink); });
84+
});
85+
86+
svr.Get("/event2", [&](const Request & /*req*/, Response &res) {
87+
cout << "connected to event2..." << endl;
88+
res.set_header("Content-Type", "text/event-stream");
89+
res.set_chunked_content_provider(
90+
[&](uint64_t /*offset*/, DataSink &sink) { ed.add_sink(&sink); });
91+
});
92+
93+
thread t([&] {
94+
int id = 0;
95+
while (true) {
96+
this_thread::sleep_for(chrono::seconds(1));
97+
cout << "send event: " << id << std::endl;
98+
std::stringstream ss;
99+
ss << "data: " << id << "\n\n";
100+
ed.send_event(ss.str());
101+
id++;
102+
}
103+
});
104+
105+
svr.listen("localhost", 1234);
106+
}

0 commit comments

Comments
 (0)