1 /* =========================================================================
2 zhttp_response - zhttp server request.
3 Class can be reused.
4
5 Copyright (c) the Contributors as noted in the AUTHORS file.
6
7 This Source Code Form is subject to the terms of the Mozilla Public
8 License, v. 2.0. If a copy of the MPL was not distributed with this
9 file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 =========================================================================
11 */
12
13 /*
14 @header
15 zhttp_response - zhttp server request.
16 Class can be reused.
17 @discuss
18 @end
19 */
20
21 #include "czmq_classes.h"
22
23 // Structure of our class
24
25 struct _zhttp_response_t {
26 uint32_t status_code;
27 zhash_t *headers;
28 char *content;
29 bool free_content;
30 };
31
32
33 // --------------------------------------------------------------------------
34 // Create a new zhttp_response
35
36 zhttp_response_t *
zhttp_response_new(void)37 zhttp_response_new (void)
38 {
39 zhttp_response_t *self = (zhttp_response_t *) zmalloc (sizeof (zhttp_response_t));
40 assert (self);
41
42 self->headers = zhash_new ();
43 zhash_autofree (self->headers);
44 self->status_code = 200;
45 self->content = NULL;
46 self->free_content = false;
47
48 return self;
49 }
50
51
52 // --------------------------------------------------------------------------
53 // Destroy the zhttp_response
54
55 void
zhttp_response_destroy(zhttp_response_t ** self_p)56 zhttp_response_destroy (zhttp_response_t **self_p)
57 {
58 assert (self_p);
59 if (*self_p) {
60 zhttp_response_t *self = *self_p;
61 zhash_destroy (&self->headers);
62
63 if (self->free_content)
64 zstr_free (&self->content);
65
66 self->content = NULL;
67 self->free_content = false;
68
69 // Free object itself
70 free (self);
71 *self_p = NULL;
72 }
73 }
74
75 int
zhttp_response_send(zhttp_response_t * self,zsock_t * sock,void ** connection_p)76 zhttp_response_send (zhttp_response_t *self, zsock_t *sock, void **connection_p) {
77 assert (self);
78 assert (connection_p);
79 assert (*connection_p);
80
81 int rc = zsock_bsend (sock, "p4p1p",
82 *connection_p, self->status_code, self->headers, self->free_content ? (byte)1 : (byte)0,
83 self->content);
84
85 if (rc == -1)
86 return rc;
87
88 *connection_p = NULL;
89 self->headers = zhash_new ();
90 zhash_autofree (self->headers);
91 self->content = NULL;
92 self->free_content = false;
93
94 return 0;
95 }
96
97
98 int
zhttp_response_recv(zhttp_response_t * self,zhttp_client_t * client,void ** arg_p,void ** arg2_p)99 zhttp_response_recv (zhttp_response_t *self, zhttp_client_t *client, void** arg_p, void** arg2_p) {
100 assert (self);
101 assert (client);
102
103 zhash_destroy (&self->headers);
104 if (self->free_content) {
105 zstr_free (&self->content);
106 self->free_content = false;
107 }
108
109 uint32_t result;
110 int rc = zsock_brecv (client, "4pp4pp", &result, arg_p, arg2_p, &self->status_code, &self->headers, &self->content);
111
112 if (rc == -1) {
113 self->headers = zhash_new ();
114 zhash_autofree (self->headers);
115
116 return -1;
117 }
118
119 self->free_content = self->content != NULL;
120
121 if (result != 0) {
122 zhash_destroy(&self->headers);
123 self->headers = zhash_new ();
124 zhash_autofree (self->headers);
125
126 errno = result;
127 return -1;
128 }
129
130 return 0;
131 }
132
133 const char *
zhttp_response_content_type(zhttp_response_t * self)134 zhttp_response_content_type (zhttp_response_t *self) {
135 assert (self);
136
137 return (const char*)zhash_lookup (self->headers, "Content-Type");
138 }
139
140
141 void
zhttp_response_set_content_type(zhttp_response_t * self,const char * content_type)142 zhttp_response_set_content_type (zhttp_response_t *self, const char* content_type) {
143 assert (self);
144 zhash_insert (self->headers, "Content-Type", (void*) content_type);
145 }
146
147
148 uint32_t
zhttp_response_status_code(zhttp_response_t * self)149 zhttp_response_status_code (zhttp_response_t *self) {
150 assert (self);
151
152 return self->status_code;
153 }
154
155
156 void
zhttp_response_set_status_code(zhttp_response_t * self,uint32_t status_code)157 zhttp_response_set_status_code (zhttp_response_t *self, uint32_t status_code) {
158 assert (self);
159
160 self->status_code = status_code;
161 }
162
163
164 zhash_t *
zhttp_response_headers(zhttp_response_t * self)165 zhttp_response_headers (zhttp_response_t *self) {
166 assert (self);
167
168 return self->headers;
169 }
170
171
172 size_t
zhttp_response_content_length(zhttp_response_t * self)173 zhttp_response_content_length (zhttp_response_t *self) {
174 assert (self);
175
176 if (!self->content)
177 return 0;
178
179 return strlen (self->content);
180 }
181
182 const char *
zhttp_response_content(zhttp_response_t * self)183 zhttp_response_content (zhttp_response_t *self) {
184 assert (self);
185
186 return self->content;
187 }
188
189
190 char *
zhttp_response_get_content(zhttp_response_t * self)191 zhttp_response_get_content (zhttp_response_t *self) {
192 assert (self);
193
194
195 if (self->content == NULL)
196 return NULL;
197
198 char* content = self->content;
199
200 // If the we don't own the content we can move the ownership, so we must duplicate the content
201 if (!self->free_content)
202 content = strdup (content);
203
204 self->content = NULL;
205 self->free_content = false;
206
207 return content;
208 }
209
210 void
zhttp_response_set_content(zhttp_response_t * self,char ** content)211 zhttp_response_set_content (zhttp_response_t *self, char **content) {
212 assert (self);
213 assert (content);
214
215 if (self->free_content)
216 zstr_free (&self->content);
217
218 self->free_content = true;
219 self->content = *content;
220 *content = NULL;
221 }
222
223
224 void
zhttp_response_set_content_const(zhttp_response_t * self,const char * content)225 zhttp_response_set_content_const (zhttp_response_t *self, const char *content) {
226 assert (self);
227 assert (content);
228
229 if (self->free_content)
230 zstr_free (&self->content);
231
232 self->free_content = false;
233 self->content = (char*) content;
234 }
235
236
237 void
zhttp_response_reset_content(zhttp_response_t * self)238 zhttp_response_reset_content (zhttp_response_t *self) {
239 assert (self);
240
241 if (self->free_content)
242 zstr_free (&self->content);
243
244 self->free_content = false;
245 self->content = NULL;
246 }
247
248 void
zhttp_response_test(bool verbose)249 zhttp_response_test (bool verbose) {
250
251 }
252