1 module soup.MessageBody; 2 3 private import glib.ConstructionException; 4 private import glib.MemorySlice; 5 private import glib.Str; 6 private import gobject.ObjectG; 7 private import soup.Buffer; 8 private import soup.c.functions; 9 public import soup.c.types; 10 11 12 /** 13 * #SoupMessageBody represents the request or response body of a 14 * #SoupMessage. 15 * 16 * In addition to #SoupMessageBody, libsoup also defines a "smaller" 17 * data buffer type, #SoupBuffer, which is primarily used as a 18 * component of #SoupMessageBody. In particular, when using chunked 19 * encoding to transmit or receive a message, each chunk is 20 * represented as a #SoupBuffer. 21 */ 22 public final class MessageBody 23 { 24 /** the main Gtk struct */ 25 protected SoupMessageBody* soupMessageBody; 26 protected bool ownedRef; 27 28 /** Get the main Gtk struct */ 29 public SoupMessageBody* getMessageBodyStruct(bool transferOwnership = false) 30 { 31 if (transferOwnership) 32 ownedRef = false; 33 return soupMessageBody; 34 } 35 36 /** the main Gtk struct as a void* */ 37 protected void* getStruct() 38 { 39 return cast(void*)soupMessageBody; 40 } 41 42 /** 43 * Sets our main struct and passes it to the parent class. 44 */ 45 public this (SoupMessageBody* soupMessageBody, bool ownedRef = false) 46 { 47 this.soupMessageBody = soupMessageBody; 48 this.ownedRef = ownedRef; 49 } 50 51 ~this () 52 { 53 if ( ownedRef ) 54 soup_message_body_free(soupMessageBody); 55 } 56 57 58 /** 59 * the data 60 */ 61 public @property string data() 62 { 63 return Str.toString(soupMessageBody.data); 64 } 65 66 /** Ditto */ 67 public @property void data(string value) 68 { 69 soupMessageBody.data = Str.toStringz(value); 70 } 71 72 /** 73 * length of @data 74 */ 75 public @property long length() 76 { 77 return soupMessageBody.length; 78 } 79 80 /** Ditto */ 81 public @property void length(long value) 82 { 83 soupMessageBody.length = value; 84 } 85 86 /** */ 87 public static GType getType() 88 { 89 return soup_message_body_get_type(); 90 } 91 92 /** 93 * Creates a new #SoupMessageBody. #SoupMessage uses this internally; you 94 * will not normally need to call it yourself. 95 * 96 * Returns: a new #SoupMessageBody. 97 * 98 * Throws: ConstructionException GTK+ fails to create the object. 99 */ 100 public this() 101 { 102 auto __p = soup_message_body_new(); 103 104 if(__p is null) 105 { 106 throw new ConstructionException("null returned by new"); 107 } 108 109 this(cast(SoupMessageBody*) __p); 110 } 111 112 /** 113 * Appends @length bytes from @data to @body according to @use. 114 * 115 * Params: 116 * use = how to use @data 117 * data = data to append 118 */ 119 public void append(SoupMemoryUse use, ubyte[] data) 120 { 121 soup_message_body_append(soupMessageBody, use, data.ptr, cast(size_t)data.length); 122 } 123 124 /** 125 * Appends the data from @buffer to @body. (#SoupMessageBody uses 126 * #SoupBuffers internally, so this is normally a constant-time 127 * operation that doesn't actually require copying the data in 128 * @buffer.) 129 * 130 * Params: 131 * buffer = a #SoupBuffer 132 */ 133 public void appendBuffer(Buffer buffer) 134 { 135 soup_message_body_append_buffer(soupMessageBody, (buffer is null) ? null : buffer.getBufferStruct()); 136 } 137 138 /** 139 * Appends @length bytes from @data to @body. 140 * 141 * This function is exactly equivalent to soup_message_body_append() 142 * with %SOUP_MEMORY_TAKE as second argument; it exists mainly for 143 * convenience and simplifying language bindings. 144 * 145 * Params: 146 * data = data to append 147 * 148 * Since: 2.32 149 */ 150 public void appendTake(char[] data) 151 { 152 soup_message_body_append_take(soupMessageBody, data.ptr, cast(size_t)data.length); 153 } 154 155 /** 156 * Tags @body as being complete; Call this when using chunked encoding 157 * after you have appended the last chunk. 158 */ 159 public void complete() 160 { 161 soup_message_body_complete(soupMessageBody); 162 } 163 164 /** 165 * Fills in @body's data field with a buffer containing all of the 166 * data in @body (plus an additional '\0' byte not counted by @body's 167 * length field). 168 * 169 * Returns: a #SoupBuffer containing the same data as @body. 170 * (You must free this buffer if you do not want it.) 171 */ 172 public Buffer flatten() 173 { 174 auto __p = soup_message_body_flatten(soupMessageBody); 175 176 if(__p is null) 177 { 178 return null; 179 } 180 181 return ObjectG.getDObject!(Buffer)(cast(SoupBuffer*) __p, true); 182 } 183 184 /** 185 * Frees @body. You will not normally need to use this, as 186 * #SoupMessage frees its associated message bodies automatically. 187 */ 188 public void free() 189 { 190 soup_message_body_free(soupMessageBody); 191 ownedRef = false; 192 } 193 194 /** 195 * Gets the accumulate flag on @body; see 196 * soup_message_body_set_accumulate() for details. 197 * 198 * Returns: the accumulate flag for @body. 199 * 200 * Since: 2.24 201 */ 202 public bool getAccumulate() 203 { 204 return soup_message_body_get_accumulate(soupMessageBody) != 0; 205 } 206 207 /** 208 * Gets a #SoupBuffer containing data from @body starting at @offset. 209 * The size of the returned chunk is unspecified. You can iterate 210 * through the entire body by first calling 211 * soup_message_body_get_chunk() with an offset of 0, and then on each 212 * successive call, increment the offset by the length of the 213 * previously-returned chunk. 214 * 215 * If @offset is greater than or equal to the total length of @body, 216 * then the return value depends on whether or not 217 * soup_message_body_complete() has been called or not; if it has, 218 * then soup_message_body_get_chunk() will return a 0-length chunk 219 * (indicating the end of @body). If it has not, then 220 * soup_message_body_get_chunk() will return %NULL (indicating that 221 * @body may still potentially have more data, but that data is not 222 * currently available). 223 * 224 * Params: 225 * offset = an offset 226 * 227 * Returns: a #SoupBuffer, or %NULL. 228 */ 229 public Buffer getChunk(long offset) 230 { 231 auto __p = soup_message_body_get_chunk(soupMessageBody, offset); 232 233 if(__p is null) 234 { 235 return null; 236 } 237 238 return ObjectG.getDObject!(Buffer)(cast(SoupBuffer*) __p, true); 239 } 240 241 /** 242 * Handles the #SoupMessageBody part of receiving a chunk of data from 243 * the network. Normally this means appending @chunk to @body, exactly 244 * as with soup_message_body_append_buffer(), but if you have set 245 * @body's accumulate flag to %FALSE, then that will not happen. 246 * 247 * This is a low-level method which you should not normally need to 248 * use. 249 * 250 * Params: 251 * chunk = a #SoupBuffer received from the network 252 * 253 * Since: 2.24 254 */ 255 public void gotChunk(Buffer chunk) 256 { 257 soup_message_body_got_chunk(soupMessageBody, (chunk is null) ? null : chunk.getBufferStruct()); 258 } 259 260 /** 261 * Sets or clears the accumulate flag on @body. (The default value is 262 * %TRUE.) If set to %FALSE, @body's %data field will not be filled in 263 * after the body is fully sent/received, and the chunks that make up 264 * @body may be discarded when they are no longer needed. 265 * 266 * In particular, if you set this flag to %FALSE on an "incoming" 267 * message body (that is, the #SoupMessage:response_body of a 268 * client-side message, or #SoupMessage:request_body of a server-side 269 * message), this will cause each chunk of the body to be discarded 270 * after its corresponding #SoupMessage::got_chunk signal is emitted. 271 * (This is equivalent to setting the deprecated 272 * %SOUP_MESSAGE_OVERWRITE_CHUNKS flag on the message.) 273 * 274 * If you set this flag to %FALSE on the #SoupMessage:response_body of 275 * a server-side message, it will cause each chunk of the body to be 276 * discarded after its corresponding #SoupMessage::wrote_chunk signal 277 * is emitted. 278 * 279 * If you set the flag to %FALSE on the #SoupMessage:request_body of a 280 * client-side message, it will block the accumulation of chunks into 281 * @body's %data field, but it will not normally cause the chunks to 282 * be discarded after being written like in the server-side 283 * #SoupMessage:response_body case, because the request body needs to 284 * be kept around in case the request needs to be sent a second time 285 * due to redirection or authentication. However, if you set the 286 * %SOUP_MESSAGE_CAN_REBUILD flag on the message, then the chunks will 287 * be discarded, and you will be responsible for recreating the 288 * request body after the #SoupMessage::restarted signal is emitted. 289 * 290 * Params: 291 * accumulate = whether or not to accumulate body chunks in @body 292 * 293 * Since: 2.24 294 */ 295 public void setAccumulate(bool accumulate) 296 { 297 soup_message_body_set_accumulate(soupMessageBody, accumulate); 298 } 299 300 /** 301 * Deletes all of the data in @body. 302 */ 303 public void truncate() 304 { 305 soup_message_body_truncate(soupMessageBody); 306 } 307 308 /** 309 * Handles the #SoupMessageBody part of writing a chunk of data to the 310 * network. Normally this is a no-op, but if you have set @body's 311 * accumulate flag to %FALSE, then this will cause @chunk to be 312 * discarded to free up memory. 313 * 314 * This is a low-level method which you should not need to use, and 315 * there are further restrictions on its proper use which are not 316 * documented here. 317 * 318 * Params: 319 * chunk = a #SoupBuffer returned from soup_message_body_get_chunk() 320 * 321 * Since: 2.24 322 */ 323 public void wroteChunk(Buffer chunk) 324 { 325 soup_message_body_wrote_chunk(soupMessageBody, (chunk is null) ? null : chunk.getBufferStruct()); 326 } 327 }