aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsilvioprog <silvioprog@gmail.com>2019-02-10 21:13:57 -0300
committersilvioprog <silvioprog@gmail.com>2019-02-10 21:13:57 -0300
commite2c268e3796557560fb2ffe3c2e9c18f74fc9471 (patch)
tree2b29ec92457917b9f02a2b4508cc81dac8f12a3c
parent154d0fd6a11b813c006e775fc01ab665c5e75317 (diff)
downloadlibmicrohttpd-e2c268e3796557560fb2ffe3c2e9c18f74fc9471.tar.gz
libmicrohttpd-e2c268e3796557560fb2ffe3c2e9c18f74fc9471.zip
Added example for how to compress chunked HTTP response.
-rw-r--r--ChangeLog3
-rw-r--r--src/examples/Makefile.am8
-rw-r--r--src/examples/http_chunked_compression.c199
3 files changed, 209 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index c8775023..f591642d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,6 @@
1Sun Feb 10 21:00:37 BRT 2019
2 Added example for how to compress a chunked HTTP response. -SC
3
1Sun 10 Feb 2019 05:03:44 PM CET 4Sun 10 Feb 2019 05:03:44 PM CET
2 Releasing libmicrohttpd 0.9.63. -CG 5 Releasing libmicrohttpd 0.9.63. -CG
3 6
diff --git a/src/examples/Makefile.am b/src/examples/Makefile.am
index ce01107a..f934d6ad 100644
--- a/src/examples/Makefile.am
+++ b/src/examples/Makefile.am
@@ -70,7 +70,8 @@ endif
70 70
71if HAVE_ZLIB 71if HAVE_ZLIB
72noinst_PROGRAMS += \ 72noinst_PROGRAMS += \
73 http_compression 73 http_compression \
74 http_chunked_compression
74endif 75endif
75 76
76if HAVE_W32 77if HAVE_W32
@@ -206,8 +207,13 @@ https_fileserver_example_LDADD = \
206 207
207http_compression_SOURCES = \ 208http_compression_SOURCES = \
208 http_compression.c 209 http_compression.c
210http_chunked_compression_SOURCES = \
211 http_chunked_compression.c
209http_compression_LDADD = \ 212http_compression_LDADD = \
210 $(top_builddir)/src/microhttpd/libmicrohttpd.la 213 $(top_builddir)/src/microhttpd/libmicrohttpd.la
214http_chunked_compression_LDADD = \
215 $(top_builddir)/src/microhttpd/libmicrohttpd.la
211if HAVE_ZLIB 216if HAVE_ZLIB
212 http_compression_LDADD += -lz 217 http_compression_LDADD += -lz
218 http_chunked_compression_LDADD += -lz
213endif \ No newline at end of file 219endif \ No newline at end of file
diff --git a/src/examples/http_chunked_compression.c b/src/examples/http_chunked_compression.c
new file mode 100644
index 00000000..167771fa
--- /dev/null
+++ b/src/examples/http_chunked_compression.c
@@ -0,0 +1,199 @@
1/*
2 This file is part of libmicrohttpd
3 Copyright (C) 2019 Christian Grothoff (and other contributing authors)
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18*/
19/**
20 * @file http_chunked_compression.c
21 * @brief example for how to compress a chunked HTTP response
22 * @author Silvio Clecio (silvioprog)
23 */
24
25#include "platform.h"
26#include <zlib.h>
27#include <microhttpd.h>
28
29#define CHUNK 16384
30
31struct Holder {
32 FILE *file;
33 z_stream stream;
34 void *buf;
35};
36
37static int
38compress_buf (z_stream *strm, const void *src, size_t src_size, size_t *offset, void **dest, size_t *dest_size,
39 void *tmp)
40{
41 unsigned int have;
42 int ret;
43 int flush;
44 *dest = NULL;
45 *dest_size = 0;
46 do
47 {
48 if (src_size > CHUNK)
49 {
50 strm->avail_in = CHUNK;
51 src_size -= CHUNK;
52 flush = Z_NO_FLUSH;
53 }
54 else
55 {
56 strm->avail_in = (uInt) src_size;
57 flush = Z_SYNC_FLUSH;
58 }
59 *offset += strm->avail_in;
60 strm->next_in = (Bytef *) src;
61 do
62 {
63 strm->avail_out = CHUNK;
64 strm->next_out = tmp;
65 ret = deflate (strm, flush);
66 have = CHUNK - strm->avail_out;
67 *dest_size += have;
68 *dest = realloc (*dest, *dest_size);
69 if (NULL == *dest)
70 return MHD_NO;
71 memcpy ((*dest) + ((*dest_size) - have), tmp, have);
72 }
73 while (0 == strm->avail_out);
74 }
75 while (flush != Z_SYNC_FLUSH);
76 return (Z_OK == ret) ? MHD_YES : MHD_NO;
77}
78
79static ssize_t
80read_cb (void *cls, uint64_t pos, char *mem, size_t size)
81{
82 struct Holder *holder = cls;
83 void *src;
84 void *buf;
85 src = malloc (size);
86 if (NULL == src)
87 return MHD_CONTENT_READER_END_WITH_ERROR;
88 size = fread (src, 1, size, holder->file);
89 if (size < 0)
90 {
91 size = MHD_CONTENT_READER_END_WITH_ERROR;
92 goto done;
93 }
94 if (0 == size)
95 {
96 size = MHD_CONTENT_READER_END_OF_STREAM;
97 goto done;
98 }
99 if (MHD_YES != compress_buf (&holder->stream, src, size, &pos, &buf, &size, holder->buf))
100 size = MHD_CONTENT_READER_END_WITH_ERROR;
101 else
102 {
103 memcpy (mem, buf, size);
104 free (buf);
105 }
106done:
107 free (src);
108 return size;
109}
110
111static void
112free_cb (void *cls)
113{
114 struct Holder *holder = cls;
115 fclose (holder->file);
116 deflateEnd (&holder->stream);
117 free (holder->buf);
118 free (holder);
119}
120
121static int
122ahc_echo (void *cls, struct MHD_Connection *con, const char *url, const char *method, const char *version,
123 const char *upload_data, size_t *upload_size, void **ptr)
124{
125 struct Holder *holder;
126 struct MHD_Response *res;
127 int ret;
128 (void) cls;
129 (void) url;
130 (void) method;
131 (void) version;
132 (void) upload_data;
133 (void) upload_size;
134 if (NULL == *ptr)
135 {
136 *ptr = (void *) 1;
137 return MHD_YES;
138 }
139 *ptr = NULL;
140 holder = calloc (1, sizeof (struct Holder));
141 if (!holder)
142 return MHD_NO;
143 holder->file = fopen (__FILE__, "rb");
144 if (NULL == holder->file)
145 goto file_error;
146 ret = deflateInit(&holder->stream, Z_BEST_COMPRESSION);
147 if (ret != Z_OK)
148 goto stream_error;
149 holder->buf = malloc (CHUNK);
150 if (NULL == holder->buf)
151 goto buf_error;
152 res = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN, 1024, &read_cb, holder, &free_cb);
153 if (NULL == res)
154 goto error;
155 ret = MHD_add_response_header (res, MHD_HTTP_HEADER_CONTENT_ENCODING, "deflate");
156 if (MHD_YES != ret)
157 goto res_error;
158 ret = MHD_add_response_header (res, MHD_HTTP_HEADER_CONTENT_TYPE, "text/x-c");
159 if (MHD_YES != ret)
160 goto res_error;
161 ret = MHD_queue_response (con, MHD_HTTP_OK, res);
162res_error:
163 MHD_destroy_response (res);
164 return ret;
165error:
166 free (holder->buf);
167buf_error:
168 deflateEnd (&holder->stream);
169stream_error:
170 fclose (holder->file);
171file_error:
172 free (holder);
173 return MHD_NO;
174}
175
176int
177main (int argc, char *const *argv)
178{
179 struct MHD_Daemon *d;
180 unsigned int port;
181 if ((argc != 2) ||
182 (1 != sscanf (argv[1], "%u", &port)) ||
183 (UINT16_MAX < port))
184 {
185 fprintf (stderr, "%s PORT\n", argv[0]);
186 return 1;
187 }
188 d = MHD_start_daemon (MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD, (uint16_t) port, NULL, NULL,
189 &ahc_echo, NULL,
190 MHD_OPTION_END);
191 if (NULL == d)
192 return 1;
193 if (0 == port)
194 MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT, &port);
195 fprintf (stdout, "HTTP server running at http://localhost:%u\n\nPress ENTER to stop the server ...\n", port);
196 (void) getc (stdin);
197 MHD_stop_daemon (d);
198 return 0;
199}