1 module soup.MessageHeaders; 2 3 private import glib.ConstructionException; 4 private import glib.HashTable; 5 private import glib.Str; 6 private import gobject.ObjectG; 7 private import soup.c.functions; 8 public import soup.c.types; 9 10 11 /** 12 * #SoupMessageHeaders represents the HTTP message headers associated 13 * with a request or response. 14 */ 15 public class MessageHeaders 16 { 17 /** the main Gtk struct */ 18 protected SoupMessageHeaders* soupMessageHeaders; 19 protected bool ownedRef; 20 21 /** Get the main Gtk struct */ 22 public SoupMessageHeaders* getMessageHeadersStruct(bool transferOwnership = false) 23 { 24 if (transferOwnership) 25 ownedRef = false; 26 return soupMessageHeaders; 27 } 28 29 /** the main Gtk struct as a void* */ 30 protected void* getStruct() 31 { 32 return cast(void*)soupMessageHeaders; 33 } 34 35 /** 36 * Sets our main struct and passes it to the parent class. 37 */ 38 public this (SoupMessageHeaders* soupMessageHeaders, bool ownedRef = false) 39 { 40 this.soupMessageHeaders = soupMessageHeaders; 41 this.ownedRef = ownedRef; 42 } 43 44 ~this () 45 { 46 if ( ownedRef ) 47 soup_message_headers_free(soupMessageHeaders); 48 } 49 50 51 /** */ 52 public static GType getType() 53 { 54 return soup_message_headers_get_type(); 55 } 56 57 /** 58 * Creates a #SoupMessageHeaders. (#SoupMessage does this 59 * automatically for its own headers. You would only need to use this 60 * method if you are manually parsing or generating message headers.) 61 * 62 * Params: 63 * type = the type of headers 64 * 65 * Returns: a new #SoupMessageHeaders 66 * 67 * Throws: ConstructionException GTK+ fails to create the object. 68 */ 69 public this(SoupMessageHeadersType type) 70 { 71 auto __p = soup_message_headers_new(type); 72 73 if(__p is null) 74 { 75 throw new ConstructionException("null returned by new"); 76 } 77 78 this(cast(SoupMessageHeaders*) __p); 79 } 80 81 /** 82 * Appends a new header with name @name and value @value to @hdrs. (If 83 * there is an existing header with name @name, then this creates a 84 * second one, which is only allowed for list-valued headers; see also 85 * soup_message_headers_replace().) 86 * 87 * The caller is expected to make sure that @name and @value are 88 * syntactically correct. 89 * 90 * Params: 91 * name = the header name to add 92 * value = the new value of @name 93 */ 94 public void append(string name, string value) 95 { 96 soup_message_headers_append(soupMessageHeaders, Str.toStringz(name), Str.toStringz(value)); 97 } 98 99 /** 100 * Removes all the headers listed in the Connection header. 101 * 102 * Since: 2.36 103 */ 104 public void cleanConnectionHeaders() 105 { 106 soup_message_headers_clean_connection_headers(soupMessageHeaders); 107 } 108 109 /** 110 * Clears @hdrs. 111 */ 112 public void clear() 113 { 114 soup_message_headers_clear(soupMessageHeaders); 115 } 116 117 alias foreac = foreach_; 118 /** 119 * Calls @func once for each header value in @hdrs. 120 * 121 * Beware that unlike soup_message_headers_get(), this processes the 122 * headers in exactly the way they were added, rather than 123 * concatenating multiple same-named headers into a single value. 124 * (This is intentional; it ensures that if you call 125 * soup_message_headers_append() multiple times with the same name, 126 * then the I/O code will output multiple copies of the header when 127 * sending the message to the remote implementation, which may be 128 * required for interoperability in some cases.) 129 * 130 * You may not modify the headers from @func. 131 * 132 * Params: 133 * func = callback function to run for each header 134 * userData = data to pass to @func 135 */ 136 public void foreach_(SoupMessageHeadersForeachFunc func, void* userData) 137 { 138 soup_message_headers_foreach(soupMessageHeaders, func, userData); 139 } 140 141 /** 142 * Frees @hdrs. 143 */ 144 public void free() 145 { 146 soup_message_headers_free(soupMessageHeaders); 147 ownedRef = false; 148 } 149 150 /** 151 * Frees the array of ranges returned from soup_message_headers_get_ranges(). 152 * 153 * Params: 154 * ranges = an array of #SoupRange 155 * 156 * Since: 2.26 157 */ 158 public void freeRanges(SoupRange* ranges) 159 { 160 soup_message_headers_free_ranges(soupMessageHeaders, ranges); 161 } 162 163 /** 164 * Gets the value of header @name in @hdrs. 165 * 166 * This method was supposed to work correctly for both single-valued 167 * and list-valued headers, but because some HTTP clients/servers 168 * mistakenly send multiple copies of headers that are supposed to be 169 * single-valued, it sometimes returns incorrect results. To fix this, 170 * the methods soup_message_headers_get_one() and 171 * soup_message_headers_get_list() were introduced, so callers can 172 * explicitly state which behavior they are expecting. 173 * 174 * Deprecated: Use soup_message_headers_get_one() or 175 * soup_message_headers_get_list() instead. 176 * 177 * Params: 178 * name = header name 179 * 180 * Returns: as with soup_message_headers_get_list(). 181 */ 182 public string get(string name) 183 { 184 return Str.toString(soup_message_headers_get(soupMessageHeaders, Str.toStringz(name))); 185 } 186 187 /** 188 * Looks up the "Content-Disposition" header in @hdrs, parses it, and 189 * returns its value in *@disposition and *@params. @params can be 190 * %NULL if you are only interested in the disposition-type. 191 * 192 * In HTTP, the most common use of this header is to set a 193 * disposition-type of "attachment", to suggest to the browser that a 194 * response should be saved to disk rather than displayed in the 195 * browser. If @params contains a "filename" parameter, this is a 196 * suggestion of a filename to use. (If the parameter value in the 197 * header contains an absolute or relative path, libsoup will truncate 198 * it down to just the final path component, so you do not need to 199 * test this yourself.) 200 * 201 * Content-Disposition is also used in "multipart/form-data", however 202 * this is handled automatically by #SoupMultipart and the associated 203 * form methods. 204 * 205 * Params: 206 * disposition = return location for the 207 * disposition-type, or %NULL 208 * params = return 209 * location for the Content-Disposition parameters, or %NULL 210 * 211 * Returns: %TRUE if @hdrs contains a "Content-Disposition" 212 * header, %FALSE if not (in which case *@disposition and *@params 213 * will be unchanged). 214 * 215 * Since: 2.26 216 */ 217 public bool getContentDisposition(out string disposition, out HashTable params) 218 { 219 char* outdisposition = null; 220 GHashTable* outparams = null; 221 222 auto __p = soup_message_headers_get_content_disposition(soupMessageHeaders, &outdisposition, &outparams) != 0; 223 224 disposition = Str.toString(outdisposition); 225 params = new HashTable(outparams); 226 227 return __p; 228 } 229 230 /** 231 * Gets the message body length that @hdrs declare. This will only 232 * be non-0 if soup_message_headers_get_encoding() returns 233 * %SOUP_ENCODING_CONTENT_LENGTH. 234 * 235 * Returns: the message body length declared by @hdrs. 236 */ 237 public long getContentLength() 238 { 239 return soup_message_headers_get_content_length(soupMessageHeaders); 240 } 241 242 /** 243 * Parses @hdrs's Content-Range header and returns it in @start, 244 * @end, and @total_length. If the total length field in the header 245 * was specified as "*", then @total_length will be set to -1. 246 * 247 * Params: 248 * start = return value for the start of the range 249 * end = return value for the end of the range 250 * totalLength = return value for the total length of the 251 * resource, or %NULL if you don't care. 252 * 253 * Returns: %TRUE if @hdrs contained a "Content-Range" header 254 * containing a byte range which could be parsed, %FALSE otherwise. 255 * 256 * Since: 2.26 257 */ 258 public bool getContentRange(out long start, out long end, out long totalLength) 259 { 260 return soup_message_headers_get_content_range(soupMessageHeaders, &start, &end, &totalLength) != 0; 261 } 262 263 /** 264 * Looks up the "Content-Type" header in @hdrs, parses it, and returns 265 * its value in *@content_type and *@params. @params can be %NULL if you 266 * are only interested in the content type itself. 267 * 268 * Params: 269 * params = return location for the Content-Type parameters (eg, "charset"), or 270 * %NULL 271 * 272 * Returns: a string with the value of the 273 * "Content-Type" header or %NULL if @hdrs does not contain that 274 * header or it cannot be parsed (in which case *@params will be 275 * unchanged). 276 * 277 * Since: 2.26 278 */ 279 public string getContentType(out HashTable params) 280 { 281 GHashTable* outparams = null; 282 283 auto retStr = soup_message_headers_get_content_type(soupMessageHeaders, &outparams); 284 285 params = new HashTable(outparams); 286 287 return Str.toString(retStr); 288 } 289 290 /** 291 * Gets the message body encoding that @hdrs declare. This may not 292 * always correspond to the encoding used on the wire; eg, a HEAD 293 * response may declare a Content-Length or Transfer-Encoding, but 294 * it will never actually include a body. 295 * 296 * Returns: the encoding declared by @hdrs. 297 */ 298 public SoupEncoding getEncoding() 299 { 300 return soup_message_headers_get_encoding(soupMessageHeaders); 301 } 302 303 /** 304 * Gets the expectations declared by @hdrs's "Expect" header. 305 * Currently this will either be %SOUP_EXPECTATION_CONTINUE or 306 * %SOUP_EXPECTATION_UNRECOGNIZED. 307 * 308 * Returns: the contents of @hdrs's "Expect" header 309 */ 310 public SoupExpectation getExpectations() 311 { 312 return soup_message_headers_get_expectations(soupMessageHeaders); 313 } 314 315 /** 316 * Gets the type of headers. 317 * 318 * Returns: the header's type. 319 * 320 * Since: 2.50 321 */ 322 public SoupMessageHeadersType getHeadersType() 323 { 324 return soup_message_headers_get_headers_type(soupMessageHeaders); 325 } 326 327 /** 328 * Gets the value of header @name in @hdrs. Use this for headers whose 329 * values are comma-delimited lists, and which are therefore allowed 330 * to appear multiple times in the headers. For non-list-valued 331 * headers, use soup_message_headers_get_one(). 332 * 333 * If @name appears multiple times in @hdrs, 334 * soup_message_headers_get_list() will concatenate all of the values 335 * together, separated by commas. This is sometimes awkward to parse 336 * (eg, WWW-Authenticate, Set-Cookie), but you have to be able to deal 337 * with it anyway, because the HTTP spec explicitly states that this 338 * transformation is allowed, and so an upstream proxy could do the 339 * same thing. 340 * 341 * Params: 342 * name = header name 343 * 344 * Returns: the header's value or %NULL if not found. 345 * 346 * Since: 2.28 347 */ 348 public string getList(string name) 349 { 350 return Str.toString(soup_message_headers_get_list(soupMessageHeaders, Str.toStringz(name))); 351 } 352 353 /** 354 * Gets the value of header @name in @hdrs. Use this for headers whose 355 * values are <emphasis>not</emphasis> comma-delimited lists, and 356 * which therefore can only appear at most once in the headers. For 357 * list-valued headers, use soup_message_headers_get_list(). 358 * 359 * If @hdrs does erroneously contain multiple copies of the header, it 360 * is not defined which one will be returned. (Ideally, it will return 361 * whichever one makes libsoup most compatible with other HTTP 362 * implementations.) 363 * 364 * Params: 365 * name = header name 366 * 367 * Returns: the header's value or %NULL if not found. 368 * 369 * Since: 2.28 370 */ 371 public string getOne(string name) 372 { 373 return Str.toString(soup_message_headers_get_one(soupMessageHeaders, Str.toStringz(name))); 374 } 375 376 /** 377 * Parses @hdrs's Range header and returns an array of the requested 378 * byte ranges. The returned array must be freed with 379 * soup_message_headers_free_ranges(). 380 * 381 * If @total_length is non-0, its value will be used to adjust the 382 * returned ranges to have explicit start and end values, and the 383 * returned ranges will be sorted and non-overlapping. If 384 * @total_length is 0, then some ranges may have an end value of -1, 385 * as described under #SoupRange, and some of the ranges may be 386 * redundant. 387 * 388 * Beware that even if given a @total_length, this function does not 389 * check that the ranges are satisfiable. 390 * 391 * <note><para> 392 * #SoupServer has built-in handling for range requests. If your 393 * server handler returns a %SOUP_STATUS_OK response containing the 394 * complete response body (rather than pausing the message and 395 * returning some of the response body later), and there is a Range 396 * header in the request, then libsoup will automatically convert the 397 * response to a %SOUP_STATUS_PARTIAL_CONTENT response containing only 398 * the range(s) requested by the client. 399 * 400 * The only time you need to process the Range header yourself is if 401 * either you need to stream the response body rather than returning 402 * it all at once, or you do not already have the complete response 403 * body available, and only want to generate the parts that were 404 * actually requested by the client. 405 * </para></note> 406 * 407 * Params: 408 * totalLength = the total_length of the response body 409 * ranges = return location for an array 410 * of #SoupRange 411 * 412 * Returns: %TRUE if @hdrs contained a syntactically-valid 413 * "Range" header, %FALSE otherwise (in which case @range and @length 414 * will not be set). 415 * 416 * Since: 2.26 417 */ 418 public bool getRanges(long totalLength, out SoupRange[] ranges) 419 { 420 SoupRange* outranges = null; 421 int length; 422 423 auto __p = soup_message_headers_get_ranges(soupMessageHeaders, totalLength, &outranges, &length) != 0; 424 425 ranges = outranges[0 .. length]; 426 427 return __p; 428 } 429 430 /** 431 * Checks whether the list-valued header @name is present in @hdrs, 432 * and contains a case-insensitive match for @token. 433 * 434 * (If @name is present in @hdrs, then this is equivalent to calling 435 * soup_header_contains() on its value.) 436 * 437 * Params: 438 * name = header name 439 * token = token to look for 440 * 441 * Returns: %TRUE if the header is present and contains @token, 442 * %FALSE otherwise. 443 * 444 * Since: 2.50 445 */ 446 public bool headerContains(string name, string token) 447 { 448 return soup_message_headers_header_contains(soupMessageHeaders, Str.toStringz(name), Str.toStringz(token)) != 0; 449 } 450 451 /** 452 * Checks whether the header @name is present in @hdrs and is 453 * (case-insensitively) equal to @value. 454 * 455 * Params: 456 * name = header name 457 * value = expected value 458 * 459 * Returns: %TRUE if the header is present and its value is 460 * @value, %FALSE otherwise. 461 * 462 * Since: 2.50 463 */ 464 public bool headerEquals(string name, string value) 465 { 466 return soup_message_headers_header_equals(soupMessageHeaders, Str.toStringz(name), Str.toStringz(value)) != 0; 467 } 468 469 /** 470 * Removes @name from @hdrs. If there are multiple values for @name, 471 * they are all removed. 472 * 473 * Params: 474 * name = the header name to remove 475 */ 476 public void remove(string name) 477 { 478 soup_message_headers_remove(soupMessageHeaders, Str.toStringz(name)); 479 } 480 481 /** 482 * Replaces the value of the header @name in @hdrs with @value. (See 483 * also soup_message_headers_append().) 484 * 485 * The caller is expected to make sure that @name and @value are 486 * syntactically correct. 487 * 488 * Params: 489 * name = the header name to replace 490 * value = the new value of @name 491 */ 492 public void replace(string name, string value) 493 { 494 soup_message_headers_replace(soupMessageHeaders, Str.toStringz(name), Str.toStringz(value)); 495 } 496 497 /** 498 * Sets the "Content-Disposition" header in @hdrs to @disposition, 499 * optionally with additional parameters specified in @params. 500 * 501 * See soup_message_headers_get_content_disposition() for a discussion 502 * of how Content-Disposition is used in HTTP. 503 * 504 * Params: 505 * disposition = the disposition-type 506 * params = additional 507 * parameters, or %NULL 508 * 509 * Since: 2.26 510 */ 511 public void setContentDisposition(string disposition, HashTable params) 512 { 513 soup_message_headers_set_content_disposition(soupMessageHeaders, Str.toStringz(disposition), (params is null) ? null : params.getHashTableStruct()); 514 } 515 516 /** 517 * Sets the message body length that @hdrs will declare, and sets 518 * @hdrs's encoding to %SOUP_ENCODING_CONTENT_LENGTH. 519 * 520 * You do not normally need to call this; if @hdrs is set to use 521 * Content-Length encoding, libsoup will automatically set its 522 * Content-Length header for you immediately before sending the 523 * headers. One situation in which this method is useful is when 524 * generating the response to a HEAD request; Calling 525 * soup_message_headers_set_content_length() allows you to put the 526 * correct content length into the response without needing to waste 527 * memory by filling in a response body which won't actually be sent. 528 * 529 * Params: 530 * contentLength = the message body length 531 */ 532 public void setContentLength(long contentLength) 533 { 534 soup_message_headers_set_content_length(soupMessageHeaders, contentLength); 535 } 536 537 /** 538 * Sets @hdrs's Content-Range header according to the given values. 539 * (Note that @total_length is the total length of the entire resource 540 * that this is a range of, not simply @end - @start + 1.) 541 * 542 * <note><para> 543 * #SoupServer has built-in handling for range requests, and you do 544 * not normally need to call this function youself. See 545 * soup_message_headers_get_ranges() for more details. 546 * </para></note> 547 * 548 * Params: 549 * start = the start of the range 550 * end = the end of the range 551 * totalLength = the total length of the resource, or -1 if unknown 552 * 553 * Since: 2.26 554 */ 555 public void setContentRange(long start, long end, long totalLength) 556 { 557 soup_message_headers_set_content_range(soupMessageHeaders, start, end, totalLength); 558 } 559 560 /** 561 * Sets the "Content-Type" header in @hdrs to @content_type, 562 * optionally with additional parameters specified in @params. 563 * 564 * Params: 565 * contentType = the MIME type 566 * params = additional 567 * parameters, or %NULL 568 * 569 * Since: 2.26 570 */ 571 public void setContentType(string contentType, HashTable params) 572 { 573 soup_message_headers_set_content_type(soupMessageHeaders, Str.toStringz(contentType), (params is null) ? null : params.getHashTableStruct()); 574 } 575 576 /** 577 * Sets the message body encoding that @hdrs will declare. In particular, 578 * you should use this if you are going to send a request or response in 579 * chunked encoding. 580 * 581 * Params: 582 * encoding = a #SoupEncoding 583 */ 584 public void setEncoding(SoupEncoding encoding) 585 { 586 soup_message_headers_set_encoding(soupMessageHeaders, encoding); 587 } 588 589 /** 590 * Sets @hdrs's "Expect" header according to @expectations. 591 * 592 * Currently %SOUP_EXPECTATION_CONTINUE is the only known expectation 593 * value. You should set this value on a request if you are sending a 594 * large message body (eg, via POST or PUT), and want to give the 595 * server a chance to reject the request after seeing just the headers 596 * (eg, because it will require authentication before allowing you to 597 * post, or because you're POSTing to a URL that doesn't exist). This 598 * saves you from having to transmit the large request body when the 599 * server is just going to ignore it anyway. 600 * 601 * Params: 602 * expectations = the expectations to set 603 */ 604 public void setExpectations(SoupExpectation expectations) 605 { 606 soup_message_headers_set_expectations(soupMessageHeaders, expectations); 607 } 608 609 /** 610 * Sets @hdrs's Range header to request the indicated range. 611 * @start and @end are interpreted as in a #SoupRange. 612 * 613 * If you need to request multiple ranges, use 614 * soup_message_headers_set_ranges(). 615 * 616 * Params: 617 * start = the start of the range to request 618 * end = the end of the range to request 619 * 620 * Since: 2.26 621 */ 622 public void setRange(long start, long end) 623 { 624 soup_message_headers_set_range(soupMessageHeaders, start, end); 625 } 626 627 /** 628 * Sets @hdrs's Range header to request the indicated ranges. (If you 629 * only want to request a single range, you can use 630 * soup_message_headers_set_range().) 631 * 632 * Params: 633 * ranges = an array of #SoupRange 634 * length = the length of @range 635 * 636 * Since: 2.26 637 */ 638 public void setRanges(SoupRange* ranges, int length) 639 { 640 soup_message_headers_set_ranges(soupMessageHeaders, ranges, length); 641 } 642 }