Skip to content

Commit 5efefa9

Browse files
committed
Refactor code structure for improved readability and maintainability
1 parent 3a42e93 commit 5efefa9

File tree

4 files changed

+1032
-1034
lines changed

4 files changed

+1032
-1034
lines changed

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -873,6 +873,26 @@ res = cli.Options("*");
873873
res = cli.Options("/resource/foo");
874874
```
875875

876+
### Streaming API (C++20)
877+
878+
Process large responses without loading everything into memory. Requires C++20.
879+
880+
```c++
881+
#include "httplib.h"
882+
#include "httplib-stream.h"
883+
884+
httplib::Client cli("localhost", 8080);
885+
886+
auto result = httplib::stream::Get(cli, "/large-file");
887+
if (result) {
888+
for (auto chunk : result.body()) {
889+
process(chunk); // Process each chunk as it arrives
890+
}
891+
}
892+
```
893+
894+
All HTTP methods are supported: `stream::Get`, `Post`, `Put`, `Patch`, `Delete`, `Head`, `Options`. See `httplib-stream.h` for details.
895+
876896
### Timeout
877897
878898
```c++

httplib-stream.h

Lines changed: 226 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -222,17 +222,29 @@ inline Generator<std::string_view> stream_body(ClientImpl::StreamHandle handle,
222222
// stream namespace - C++20 streaming API
223223
//------------------------------------------------------------------------------
224224
//
225-
// Provides a convenient interface for streaming HTTP response bodies.
226-
// Data is read directly from the socket without buffering.
225+
// Provides streaming HTTP response handling. Data is read directly from the
226+
// socket without buffering the entire response in memory. Ideal for:
227+
// - Large file downloads
228+
// - Server-Sent Events (SSE)
229+
// - Any streaming API
230+
//
231+
// Note: Connection is not reused (Keep-Alive disabled) since socket ownership
232+
// is transferred to StreamHandle. For repeated small requests where connection
233+
// reuse matters, use client.Get() instead.
227234
//
228235
// Usage:
229-
// auto result = httplib::stream::Get(client, "/large-file");
236+
// httplib::Client cli("example.com", 80);
237+
// auto result = httplib::stream::Get(cli, "/large-file");
230238
// if (result) {
231239
// for (auto chunk : result.body()) {
232240
// process(chunk);
233241
// }
234242
// }
235243
//
244+
// Also works with SSLClient:
245+
// httplib::SSLClient cli("example.com", 443);
246+
// auto result = httplib::stream::Get(cli, "/secure-data");
247+
//
236248

237249
namespace stream {
238250

@@ -291,43 +303,225 @@ class Result {
291303
ClientImpl::StreamHandle handle_;
292304
};
293305

294-
//------------------------------------------------------------------------------
295-
// Streaming HTTP request functions
296-
//------------------------------------------------------------------------------
297-
//
298-
// stream::Get reads response body directly from the socket without buffering
299-
// the entire response in memory. This is ideal for:
300-
// - Large file downloads
301-
// - Server-Sent Events (SSE)
302-
// - Any streaming API
303-
//
304-
// Note: The connection is not reused (Keep-Alive disabled) since socket
305-
// ownership is transferred to StreamHandle. For repeated small requests
306-
// where connection reuse matters, use client.Get() instead.
307-
//
308-
// Usage:
309-
// auto result = httplib::stream::Get(client, "/huge-file");
310-
// for (auto chunk : result.body()) {
311-
// write_to_file(chunk);
312-
// }
313-
//
306+
// GET
314307

315-
inline Result Get(Client &cli, const std::string &path) {
316-
return Result{cli.open_stream(path)};
308+
template <typename ClientType>
309+
inline Result Get(ClientType &cli, const std::string &path) {
310+
return Result{cli.open_stream("GET", path)};
317311
}
318312

319-
inline Result Get(Client &cli, const std::string &path,
313+
template <typename ClientType>
314+
inline Result Get(ClientType &cli, const std::string &path,
320315
const Headers &headers) {
321-
return Result{cli.open_stream(path, headers)};
316+
return Result{cli.open_stream("GET", path, {}, headers)};
322317
}
323318

324-
inline Result Get(Client &cli, const std::string &path, const Params &params) {
325-
return Result{cli.open_stream(append_query_params(path, params))};
319+
template <typename ClientType>
320+
inline Result Get(ClientType &cli, const std::string &path,
321+
const Params &params) {
322+
return Result{cli.open_stream("GET", path, params)};
326323
}
327324

328-
inline Result Get(Client &cli, const std::string &path, const Params &params,
329-
const Headers &headers) {
330-
return Result{cli.open_stream(append_query_params(path, params), headers)};
325+
template <typename ClientType>
326+
inline Result Get(ClientType &cli, const std::string &path,
327+
const Params &params, const Headers &headers) {
328+
return Result{cli.open_stream("GET", path, params, headers)};
329+
}
330+
331+
// POST
332+
333+
template <typename ClientType>
334+
inline Result Post(ClientType &cli, const std::string &path,
335+
const std::string &body, const std::string &content_type) {
336+
return Result{cli.open_stream("POST", path, {}, {}, body, content_type)};
337+
}
338+
339+
template <typename ClientType>
340+
inline Result Post(ClientType &cli, const std::string &path,
341+
const Headers &headers, const std::string &body,
342+
const std::string &content_type) {
343+
return Result{cli.open_stream("POST", path, {}, headers, body, content_type)};
344+
}
345+
346+
template <typename ClientType>
347+
inline Result Post(ClientType &cli, const std::string &path,
348+
const Params &params, const std::string &body,
349+
const std::string &content_type) {
350+
return Result{cli.open_stream("POST", path, params, {}, body, content_type)};
351+
}
352+
353+
template <typename ClientType>
354+
inline Result Post(ClientType &cli, const std::string &path,
355+
const Params &params, const Headers &headers,
356+
const std::string &body, const std::string &content_type) {
357+
return Result{
358+
cli.open_stream("POST", path, params, headers, body, content_type)};
359+
}
360+
361+
// PUT
362+
363+
template <typename ClientType>
364+
inline Result Put(ClientType &cli, const std::string &path,
365+
const std::string &body, const std::string &content_type) {
366+
return Result{cli.open_stream("PUT", path, {}, {}, body, content_type)};
367+
}
368+
369+
template <typename ClientType>
370+
inline Result Put(ClientType &cli, const std::string &path,
371+
const Headers &headers, const std::string &body,
372+
const std::string &content_type) {
373+
return Result{cli.open_stream("PUT", path, {}, headers, body, content_type)};
374+
}
375+
376+
template <typename ClientType>
377+
inline Result Put(ClientType &cli, const std::string &path,
378+
const Params &params, const std::string &body,
379+
const std::string &content_type) {
380+
return Result{cli.open_stream("PUT", path, params, {}, body, content_type)};
381+
}
382+
383+
template <typename ClientType>
384+
inline Result Put(ClientType &cli, const std::string &path,
385+
const Params &params, const Headers &headers,
386+
const std::string &body, const std::string &content_type) {
387+
return Result{
388+
cli.open_stream("PUT", path, params, headers, body, content_type)};
389+
}
390+
391+
// PATCH
392+
393+
template <typename ClientType>
394+
inline Result Patch(ClientType &cli, const std::string &path,
395+
const std::string &body, const std::string &content_type) {
396+
return Result{cli.open_stream("PATCH", path, {}, {}, body, content_type)};
397+
}
398+
399+
template <typename ClientType>
400+
inline Result Patch(ClientType &cli, const std::string &path,
401+
const Headers &headers, const std::string &body,
402+
const std::string &content_type) {
403+
return Result{
404+
cli.open_stream("PATCH", path, {}, headers, body, content_type)};
405+
}
406+
407+
template <typename ClientType>
408+
inline Result Patch(ClientType &cli, const std::string &path,
409+
const Params &params, const std::string &body,
410+
const std::string &content_type) {
411+
return Result{cli.open_stream("PATCH", path, params, {}, body, content_type)};
412+
}
413+
414+
template <typename ClientType>
415+
inline Result Patch(ClientType &cli, const std::string &path,
416+
const Params &params, const Headers &headers,
417+
const std::string &body, const std::string &content_type) {
418+
return Result{
419+
cli.open_stream("PATCH", path, params, headers, body, content_type)};
420+
}
421+
422+
// DELETE
423+
424+
template <typename ClientType>
425+
inline Result Delete(ClientType &cli, const std::string &path) {
426+
return Result{cli.open_stream("DELETE", path)};
427+
}
428+
429+
template <typename ClientType>
430+
inline Result Delete(ClientType &cli, const std::string &path,
431+
const Headers &headers) {
432+
return Result{cli.open_stream("DELETE", path, {}, headers)};
433+
}
434+
435+
template <typename ClientType>
436+
inline Result Delete(ClientType &cli, const std::string &path,
437+
const std::string &body, const std::string &content_type) {
438+
return Result{cli.open_stream("DELETE", path, {}, {}, body, content_type)};
439+
}
440+
441+
template <typename ClientType>
442+
inline Result Delete(ClientType &cli, const std::string &path,
443+
const Headers &headers, const std::string &body,
444+
const std::string &content_type) {
445+
return Result{
446+
cli.open_stream("DELETE", path, {}, headers, body, content_type)};
447+
}
448+
449+
template <typename ClientType>
450+
inline Result Delete(ClientType &cli, const std::string &path,
451+
const Params &params) {
452+
return Result{cli.open_stream("DELETE", path, params)};
453+
}
454+
455+
template <typename ClientType>
456+
inline Result Delete(ClientType &cli, const std::string &path,
457+
const Params &params, const Headers &headers) {
458+
return Result{cli.open_stream("DELETE", path, params, headers)};
459+
}
460+
461+
template <typename ClientType>
462+
inline Result Delete(ClientType &cli, const std::string &path,
463+
const Params &params, const std::string &body,
464+
const std::string &content_type) {
465+
return Result{
466+
cli.open_stream("DELETE", path, params, {}, body, content_type)};
467+
}
468+
469+
template <typename ClientType>
470+
inline Result Delete(ClientType &cli, const std::string &path,
471+
const Params &params, const Headers &headers,
472+
const std::string &body, const std::string &content_type) {
473+
return Result{
474+
cli.open_stream("DELETE", path, params, headers, body, content_type)};
475+
}
476+
477+
// HEAD
478+
479+
template <typename ClientType>
480+
inline Result Head(ClientType &cli, const std::string &path) {
481+
return Result{cli.open_stream("HEAD", path)};
482+
}
483+
484+
template <typename ClientType>
485+
inline Result Head(ClientType &cli, const std::string &path,
486+
const Headers &headers) {
487+
return Result{cli.open_stream("HEAD", path, {}, headers)};
488+
}
489+
490+
template <typename ClientType>
491+
inline Result Head(ClientType &cli, const std::string &path,
492+
const Params &params) {
493+
return Result{cli.open_stream("HEAD", path, params)};
494+
}
495+
496+
template <typename ClientType>
497+
inline Result Head(ClientType &cli, const std::string &path,
498+
const Params &params, const Headers &headers) {
499+
return Result{cli.open_stream("HEAD", path, params, headers)};
500+
}
501+
502+
// OPTIONS
503+
504+
template <typename ClientType>
505+
inline Result Options(ClientType &cli, const std::string &path) {
506+
return Result{cli.open_stream("OPTIONS", path)};
507+
}
508+
509+
template <typename ClientType>
510+
inline Result Options(ClientType &cli, const std::string &path,
511+
const Headers &headers) {
512+
return Result{cli.open_stream("OPTIONS", path, {}, headers)};
513+
}
514+
515+
template <typename ClientType>
516+
inline Result Options(ClientType &cli, const std::string &path,
517+
const Params &params) {
518+
return Result{cli.open_stream("OPTIONS", path, params)};
519+
}
520+
521+
template <typename ClientType>
522+
inline Result Options(ClientType &cli, const std::string &path,
523+
const Params &params, const Headers &headers) {
524+
return Result{cli.open_stream("OPTIONS", path, params, headers)};
331525
}
332526

333527
} // namespace stream

0 commit comments

Comments
 (0)