A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
http.h
Go to the documentation of this file.
1/*
2 * MIT License
3 *
4 * Copyright (c) 2019 Maxwell Flynn
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 * Source-code taken from https://github.com/tinfoilboy/atomizes
25 * Adopted by: Miralem Mehic <miralem.mehic@ieee.org>
26 */
27
28#ifndef HTTP_CONTENT_H
29#define HTTP_CONTENT_H
30
31#include <string>
32#include <unordered_map>
33#include <cstdint>
34#include <vector>
35#include <sstream>
36#include <algorithm> // std::remove_if
37
38#include "ns3/log.h"
39
40namespace ns3 {
41
42 /**
43 * HTTP defines that any lines must be seperated with a carriage return.
44 *
45 * Define this as a constant to use across the library code and to change easily.
46 */
47 const std::string CarriageReturn = "\r\n";
48
49 /**
50 * The string for HTTP version 1.0
51 */
52 const std::string HTTPVersion1 = "HTTP/1.0";
53
54 /**
55 * The string for HTTP version 1.1
56 */
57 const std::string HTTPVersion11 = "HTTP/1.1";
58
59 /**
60 * The basic class to represent both HTTP requests and responses.
61 *
62 * Contains a method for grabbing the message as a string formatted for
63 * sending through a server or other means.
64 *
65 * Allows for setting a message body that is represented by a vector of
66 * 8-bit unsigned integers. This is to allow binary data to be sent through
67 * the message. But, you also can use the included methods to send plain strings.
68 *
69 * This class returns as many methods as possible with a reference to the current
70 * object, to try and allow for chaining methods.
71 *
72 * Note: for convenience, the header for Content-Length is automatically included
73 * as it is grabbed from the `m_body` member. Though, it is only included if the
74 * body member isn't empty.
75 */
77 {
78 public:
79
82 DELETE, /**< Http Method Delete */
83 GET, /**< Http Method GET */
84 HEAD, /**< Http Method Head */
85 PATCH, /**< Http Method Patch */
86 POST, /**< Http Method Post */
87 PUT /**< Http Method Put */
88 };
89
91 {
92 Continue = 100,
96
97 Ok = 200,
98 Created = 201,
99 Accepted = 202,
106 ImUsed = 226,
107
110 Found = 302,
111 SeeOther = 303,
113 UseProxy = 305,
116
121 NotFound = 404,
126 Conflict = 409,
127 Gone = 410,
138 Locked = 423,
140 TooEarly = 425,
146
158 };
159
160
161
162 /**
163 * To be returned with a status code in a response is a status text describing the
164 * status code by text rather than by a code.
165 *
166 * This method takes in one of those codes and tries to return a text for it.
167 */
169 {
170 switch (m_statusCode)
171 {
172 case 100:
174 case 101:
176 case 200:
178 case 201:
180 case 202:
182 case 203:
184 case 204:
186 case 205:
188 case 206:
190 case 300:
192 case 301:
194 case 302:
196 case 303:
198 case 304:
200 // 305 is deprecated and 306 is only reserved, skip
201 case 307:
203 case 308:
205 case 400:
207 case 401:
209 case 402:
210 // 402 is reserved for future use but has a status message, adding it
212 case 403:
214 case 404:
216 case 405:
218 case 406:
220 case 407:
222 case 408:
224 case 409:
226 case 410:
228 case 411:
230 case 412:
232 case 413:
234 case 414:
236 case 415:
238 case 416:
240 case 417:
242 case 418:
243 // might as well return the teapot joke
245 case 421:
247 case 425:
249 case 426:
251 case 428:
253 case 429:
255 case 431:
257 case 451:
259 case 500:
261 case 501:
263 case 502:
265 case 503:
267 case 504:
269 case 505:
271 case 506:
273 case 507:
275 case 510:
277 case 511:
279 default:
281 }
282 }
283
284 /**
285 * To be returned with a status code in a response is a status text describing the
286 * status code by text rather than by a code.
287 *
288 * This method takes in one of those codes and tries to return a text for it.
289 */
290 inline std::string StatusTextFromStatusCode(const uint16_t statusCode)
291 {
292 switch (statusCode)
293 {
294 case 100:
295 return "Continue";
296 case 101:
297 return "Switching Protocol";
298 case 200:
299 return "OK";
300 case 201:
301 return "Created";
302 case 202:
303 return "Accepted";
304 case 203:
305 return "Non-Authoritative Information";
306 case 204:
307 return "No Content";
308 case 205:
309 return "Reset Content";
310 case 206:
311 return "Partial Content";
312 case 300:
313 return "Multiple Choice";
314 case 301:
315 return "Moved Permanently";
316 case 302:
317 return "Found";
318 case 303:
319 return "See Other";
320 case 304:
321 return "Not Modified";
322 // 305 is deprecated and 306 is only reserved, skip
323 case 307:
324 return "Temporary Redirect";
325 case 308:
326 return "Permanent Redirect";
327 case 400:
328 return "Bad Request";
329 case 401:
330 return "Unauthorized";
331 case 402:
332 // 402 is reserved for future use but has a status message, adding it
333 return "Payment Required";
334 case 403:
335 return "Forbidden";
336 case 404:
337 return "Not Found";
338 case 405:
339 return "Method Not Allowed";
340 case 406:
341 return "Not Acceptable";
342 case 407:
343 return "Proxy Authentication Required";
344 case 408:
345 return "Request Timeout";
346 case 409:
347 return "Conflict";
348 case 410:
349 return "Gone";
350 case 411:
351 return "Length Required";
352 case 412:
353 return "Precondition Failed";
354 case 413:
355 return "Payload Too Large";
356 case 414:
357 return "URI Too Long";
358 case 415:
359 return "Unsupported Media Type";
360 case 416:
361 return "Requested Range Not Satisfiable";
362 case 417:
363 return "Expectation Failed";
364 case 418:
365 // might as well return the teapot joke
366 return "I'm a teapot";
367 case 421:
368 return "Misdirected Request";
369 case 425:
370 return "Too Early";
371 case 426:
372 return "Upgrade Required";
373 case 428:
374 return "Precondition Required";
375 case 429:
376 return "Too Many Requests";
377 case 431:
378 return "Request Header Fields Too Large";
379 case 451:
380 return "Unavailable for Legal Reasons";
381 case 500:
382 return "Internal Server Error";
383 case 501:
384 return "Not Implemented";
385 case 502:
386 return "Bad Gateway";
387 case 503:
388 return "Service Unavailable";
389 case 504:
390 return "Gateway Timeout";
391 case 505:
392 return "HTTP Version Not Supported";
393 case 506:
394 return "Variant Also Negotiates";
395 case 507:
396 return "Insufficient Storage";
397 case 510:
398 return "Not Extended";
399 case 511:
400 return "Network Authentication Required";
401 default:
402 return "Undefined";
403 }
404 }
405
406 /**
407 * Set a header in the map to the value provided.
408 */
409 HTTPMessage& SetHeader(const std::string& name, const std::string& value)
410 {
411 m_headers[name] = value;
412
413 if(name == "Content-Length") {
414 m_contentLength = std::stoi(value);
415 }else if(name == "Request URI"){
417 }else if(name == "Host"){
418 if(m_domain.empty()){
419 m_domain = value;
420 m_uri = value + m_uri;
421 }
422 }
423
424 return *this;
425 }
426
427 /**
428 * @return The request uri value
429 */
430 std::string GetRequestUri() const{
431 return m_request_uri;
432 }
433
434 /**
435 * Set a number of headers based on a generic map of keys and values.
436 */
437 HTTPMessage& SetHeaders(const std::unordered_map<std::string, std::string>& headers)
438 {
439 m_headers.insert(headers.begin(), headers.end());
440 return *this;
441 }
442
443 /**
444 * Get the string value of a single header from the message.
445 *
446 * Will return an empty string if the header does not exist.
447 */
448 inline std::string GetHeader(const std::string& name) const
449 {
450 auto find = m_headers.find(name);
451
452 if (find != m_headers.end())
453 return find->second;
454
455 return "";
456 }
457
458 /**
459 * Set the associated message method for this message.
460 *
461 * Use `NONE` to switch this into a response.
462 */
463 void SetMethod (const std::string& m)
464 {
465
466 if (m == "DELETE")
468 else if (m == "GET")
470 else if (m == "HEAD")
472 else if (m == "PATCH")
474 else if (m == "POST")
476 else if (m == "PUT")
478
479 }
480
482 {
483 return m_method;
484 }
485
486 std::string GetMethodToString() const
487 {
488 switch (m_method)
489 {
491 return "NONE";
492 break;
494 return "DELETE";
495 break;
496 case HTTPMessage::GET:
497 return "GET";
498 break;
500 return "HEAD";
501 break;
503 return "PATCH";
504 break;
506 return "POST";
507 break;
508 case HTTPMessage::PUT:
509 return "PUT";
510 break;
511 }
512 return "NONE";
513 }
514
515 /**
516 * Grab the uri
517 */
518 inline std::string GetUri() const
519 {
520 return m_uri;
521 }
522
523 /**
524 * Set the path of this message, which will be used if it is a request.
525 */
526 void SetPath(const std::string& url)
527 {
528 const auto schemeEndPosition = url.find("://");
529 if (schemeEndPosition != std::string::npos)
530 {
531 m_scheme = url.substr(0, schemeEndPosition);
532 m_path = url.substr(schemeEndPosition + 3);
533 }
534 else
535 {
536 m_scheme = "http";
537 m_path = url;
538 }
539
540 const auto fragmentPosition = m_path.find('#');
541
542 // remove the fragment part
543 if (fragmentPosition != std::string::npos)
544 m_path.resize(fragmentPosition);
545
546 const auto pathPosition = m_path.find('/');
547
548 if (pathPosition == std::string::npos)
549 {
551 m_path = "/";
552 }
553 else
554 {
555 m_domain = m_path.substr(0, pathPosition);
556 m_path = m_path.substr(pathPosition);
557 }
558
559 const auto portPosition = m_domain.find(':');
560
561 if (portPosition != std::string::npos)
562 {
563 m_domain.resize(portPosition);
564 }
565 m_uri = url;//;;m_domain + url;
566
567 }
568
569 /**
570 * Grab the current associated path of this message.
571 */
572 inline std::string GetPath() const
573 {
574 return m_path;
575 }
576
577 /**
578 * Set the version of this HTTP message to the string specified.
579 */
580 void SetVersion(const std::string& version)
581 {
582 m_version = version;
583 }
584
585 /**
586 * Get the current HTTP version for this message.
587 */
588 inline std::string GetVersion() const
589 {
590 return m_version;
591 }
592
593 /**
594 * Set the status code of this HTTP message.
595 */
596 void SetStatusCode(uint16_t code)
597 {
599 }
600
601 /**
602 * Get the status code for this message.
603 */
604 inline uint16_t GetStatusCode() const
605 {
606 return m_statusCode;
607 }
608
609 /**
610 * Set the status message of this HTTP message.
611 */
612 void SetStatusMessage(const std::string& message)
613 {
614 m_statusMessage = message;
615 }
616
617 /**
618 * Get the current status message for this message.
619 *
620 * Returns an autogenerated status if one isn't specified.
621 */
622 inline std::string GetStatusMessage() const
623 {
624 return m_statusMessage;
625 }
626
627 /**
628 * Takes the headers added to the message along with
629 * the body and outputs it to a `std::string` for use
630 * in client/server HTTP messages.
631 */
632 std::string ToString()
633 {
634 std::stringstream output;
635
636 // begin by forming the start line of the message
638 {
639 output << HTTPVersion11 << " " << m_statusCode << " ";
640
641 if (m_statusMessage.empty())
643 else
645 }
646 else
647 {
648 output << GetMethodToString() << " ";
649 output << m_path << " ";
651 }
652
653 // output the status lines line break to move on
655
656 // output headers to the message string
657 for (auto& header : m_headers)
658 output << header.first << ": " << header.second << CarriageReturn;
659
660 // automatically output the content length based on
661 // the size of the body member if body isn't empty
662 if (!m_contentLength && !m_body.empty()){
663 m_contentLength = m_body.size();
664 output << "Content-Length: " << m_contentLength << CarriageReturn;
665 }
666
667 // seperate headers and body with an extra carriage return
669
670 m_headersLength = output.str().size();
671
672 // convert the 8-bit unsigned body to a std::string for output
673 std::string body(m_body.begin(), m_body.end());
674
675 output << body;
676
677 return output.str();
678 }
679
681 if(m_headersLength == 0) ToString();
682 return m_headersLength;
683 }
684
688
689 /**
690 * Set the body of this message to a string value.
691 */
692 void SetMessageBody(const std::string& body)
693 {
694 SetMessageBody(std::vector<uint8_t>(body.begin(), body.end()));
695 }
696
697 /**
698 * Set the body of this message to an unsigned 8-bit binary value.
699 */
700 void SetMessageBody(const std::vector<uint8_t>& body)
701 {
702 m_body = std::vector<uint8_t>(body);
703 }
704
705 /**
706 * Get the body vector for this message.
707 */
708 inline std::vector<uint8_t>& GetMessageBody()
709 {
710 return m_body;
711 }
712
713 inline std::string GetMessageBodyString()
714 {
715 // convert the 8-bit unsigned body to a std::string for output
716 return std::string(m_body.begin(), m_body.end());
717 }
718
719 /**
720 * Return the size of the binary body vector.
721 */
722 inline size_t GetContentLength() const
723 {
724 return m_contentLength;
725 }
726
727 /**
728 * Return the amount of headers in the message.
729 */
730 inline size_t HeaderCount()
731 {
732 return m_headers.size();
733 }
734
736 const std::string& url,
737 const std::string& method
738 )
739 {
741 url,
742 method,
743 ""
744 );
745 }
746
748 const std::string& url,
749 const std::string& method,
750 const std::string& body)
751 {
752
754 url,
755 method,
756 std::vector<uint8_t>(body.begin(), body.end())
757 );
758 }
759
761 const std::string& url,
762 const std::string& method,
763 const std::vector<uint8_t>& body
764 ) {
765 SetMethod(method);
766 SetPath(url);
767 SetHeader("User-Agent", "Test Agent");
768 SetHeader("Host", m_domain);
769 SetHeader("Accept-Language", "en-us,en;q=0.5");
770 SetHeader("Accept-Encoding", "gzip,deflate");
771 SetHeader("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
772 SetHeader("Keep-Alive", "300");
773 SetHeader("Connection", "keep-alive");
774 SetHeader("Cookie", "PHPSESSID=r2t5uvjq435r4q7ib3vtdjq120");
775 SetHeader("Pragma", "no-cache");
776 SetHeader("Cache-Control", "no-cache");
777 SetHeader("Content-Length", std::to_string(body.size()) );
779 }
780
782 const HttpStatus status
783 ){
785 status,
786 ""
787 );
788 }
789
791 const HttpStatus status,
792 const std::string& body
793 ){
795 status,
796 std::vector<uint8_t>(body.begin(), body.end())
797 );
798 }
799
801 const HttpStatus status,
802 const std::vector<uint8_t>& body
803 ){
804 //response
805 SetMethod("NONE");
806 SetStatusCode(status);
807 SetHeader("Server", "QKDNetSim KMS/3.36");
808 SetHeader("Date", "Sat, 28 Aug 2022 04:36:25 GMT");
809 SetHeader("Connection", "close");
810 SetHeader("Pragma", "public");
811 SetHeader("Content-Encoding", "gzip");
812 SetHeader("Vary", "Accept-Encoding, Cookie");
813 SetHeader("Cache-Control", "max-age=3600, public");
814 SetHeader("Content-Length", std::to_string(body.size()) );
816 }
818 const HttpStatus status,
819 const std::string& body,
820 const std::unordered_map<std::string, std::string>& headers
821 ){
822 SetHeaders(headers);
824 status,
825 std::vector<uint8_t>(body.begin(), body.end())
826 );
827 }
828
830 const HttpStatus status,
831 const std::vector<uint8_t>& body,
832 const std::unordered_map<std::string, std::string>& headers
833 ){
834 SetHeaders(headers);
836 status,
837 body
838 );
839 }
840
842 {
844 }
845
846 bool IsFragmented() const
847 {
848 return m_fragmented;
849 }
850
851 private:
852 /**
853 * The HTTP method for this message.
854 *
855 * Defaults to `NONE` denoting a response.
856 */
858
859 /**
860 * A status code for this message.
861 *
862 * This is ignored if this is a request, as requests have no notion of statuses.
863 */
864 uint16_t m_statusCode = 0;
865
866 /**
867 * A status message to be associated with the status code for this message.
868 *
869 * Keep blank to use an automatically generated status message.
870 */
871 std::string m_statusMessage = "";
872
873 /**
874 * The path for the resource specified in the message. Only used for a request.
875 *
876 * Defaults to blank.
877 */
878 std::string m_path = "";
879
880 std::string m_scheme;
881 std::string m_domain;
882 std::string m_uri;
883 std::string m_request_uri;
884
885 /**
886 * The version used for this HTTP message as a string.
887 *
888 * Defaults to "HTTP/1.1"
889 */
891
892 /**
893 * An `unordered_map` of headers using a `std::string` for both the key and the
894 * value.
895 */
896 std::unordered_map<std::string, std::string> m_headers;
897
898 /**
899 * A vector of unsigned 8-bit integers used to store message bodies.
900 */
901 std::vector<uint8_t> m_body;
902
903 /**
904 * Whether the payload size is less then content-length
905 * */
906 bool m_fragmented = false;
907
910
911 };
912
913 /**
914 * An enum of states that the HTTPMessageParser can be in.
915 */
916 enum class MessageParserState : uint8_t
917 {
918 NONE,
925 };
926
927 /**
928 * A basic class to parse a HTTP message, both request and response.
929 *
930 * Allows for either string data to be passed in, or for a vector of
931 * unsigned 8-bit integers to be passed in.
932 *
933 * Requires that a whole message be sent in for parsing.
934 */
936 {
937 public:
938 /**
939 * Parse a std::string to a HTTP message.
940 *
941 * Pass in a pointer to an HTTPMessage which is then written to for headers
942 * and other message data.
943 *
944 * note: this must be a complete HTTP message
945 */
946 void Parse(HTTPMessage* httpMessage, const std::string& buffer)
947 {
948
949 std::string cleanText = buffer;
951 Parse(httpMessage, std::vector<uint8_t>(cleanText.begin(), cleanText.end()));
952 }
953
954 /**
955 * Parse a binary vector to an HTTP message.
956 *
957 * Pass in a pointer to an HTTPMessage which is written to for headers and
958 * other message data.
959 *
960 * note: shrink the vector buffer before passing it in with `shrink_to_fit`
961 * otherwise empty characters will show up for the body
962 * note: must be a complete HTTP message.
963 */
964 void Parse(HTTPMessage* httpMessage, const std::vector<uint8_t>& buffer)
965 {
966 // begin by parsing the start line without knowing if it is a
967 // request or a response by setting as undetermined
969
970 // a temporary string instance used for storing characters of a
971 // current line in the message being parsed
972 std::string temp = "";
973
974 // whether to skip the next character (for a carriage return)
975 bool skipNext = false;
976
977 // the current key for a header
978 std::string headerKey = "";
979
980 // whether or not a message body is present
981 bool hasMessageBody = false;
982
983 // the index at which the message body begins
984 size_t bodyStartIndex = 0;
985
986 for (size_t index = 0; index < buffer.size(); index++)
987 {
988 uint8_t character = buffer[index];
989
990 // skip this character as it was marked
991 if (skipNext)
992 {
993 skipNext = false;
994
995 continue;
996 }
997
998 // if we are parsing the body, then we only need to grab an index and break
999 // out of this loop as we want to merely insert the data from this vector
1000 // into the body vector
1002 {
1003 hasMessageBody = true;
1004
1005 bodyStartIndex = index;
1006
1007 break;
1008 }
1009
1010 // if we are parsing the start line but neither a response or request
1012 {
1013 // if we hit a space, we have to check if the start line begins
1014 // with the HTTP version or the method verb
1015 if (character == ' ')
1016 {
1017 // this message has a leading version string, thus it is
1018 // a response and not a request
1019 if (temp == HTTPVersion1 || temp == HTTPVersion11)
1020 {
1021 httpMessage->SetMethod("NONE");
1022
1024
1025 temp = "";
1026
1027 continue;
1028 }
1029 // this must be a request, so grab the HTTPMessage::HttpMethod type
1030 // for the request, set it, and move on
1031 else
1032 {
1033 httpMessage->SetMethod(temp);
1034
1036
1037 temp = "";
1038
1039 continue;
1040 }
1041 }
1042 }
1043 // do actions for when the start line is a request
1045 {
1046 // once a space is hit, add the path to the message
1047 if (character == ' ')
1048 {
1049 httpMessage->SetPath(temp);
1050
1051 temp = "";
1052
1053 continue;
1054 }
1055 // when the beginning of a carriage return is hit, add the version string
1056 // to the message and then skip the following new line character, setting
1057 // the state of the parser to be parsing headers
1058 else if (character == '\r')
1059 {
1060 httpMessage->SetVersion(temp);
1061
1062 temp = "";
1063
1065
1066 skipNext = true;
1067
1068 continue;
1069 }
1070 }
1071 // do actions for when the start line is a response
1073 {
1074 // if we are at a space, then we have hit the status code for the response
1075 if (character == ' ' && httpMessage->GetStatusCode() == 0)
1076 {
1077 int code = std::stoi(temp);
1078
1079 httpMessage->SetStatusCode(static_cast<uint16_t>(code));
1080
1081 temp = "";
1082
1083 continue;
1084 }
1085 // if we are at a carriage return start, then set the status message for
1086 // the response, this can be blank in which it will use a generated status
1087 //
1088 // this will also set the state of the parser to move on to headers
1089 else if (character == '\r')
1090 {
1091 httpMessage->SetStatusMessage(temp);
1092
1093 temp = "";
1094
1096
1097 skipNext = true;
1098
1099 continue;
1100 }
1101 }
1102 // if we are parsing header keys and hit a colon, then the key for the header has
1103 // been fully parsed and should be added to the temporary key holder
1104 else if (state == MessageParserState::HEADER_KEY && character == ':')
1105 {
1106 headerKey = temp;
1107
1108 temp = "";
1109
1111
1112 // HTTP defines that the next character in a header should be a space
1113 // so skip that for parsing the value of the header
1114 skipNext = true;
1115
1116 continue;
1117 }
1118 // if we are parsing header values and hit the beginning of a carriage return then
1119 // it is time to add the header to the message with the key and value, and move the
1120 // state back to parsing keys
1121 else if (state == MessageParserState::HEADER_VALUE && character == '\r')
1122 {
1123 httpMessage->SetHeader(headerKey, temp);
1124
1125 headerKey = "";
1126 temp = "";
1127
1129
1130 // skip the next character as it will just be a newline
1131 skipNext = true;
1132
1133 continue;
1134 }
1135 // if we are parsing header keys and we hit a carriage return, then we should assume
1136 // that the headers have ended, and that we are now parsing a message body.
1137 else if (state == MessageParserState::HEADER_KEY && character == '\r')
1138 {
1139 temp = "";
1140
1142
1143 // skip the next character as it'll be a newline
1144 skipNext = true;
1145
1146 continue;
1147 }
1148
1149 temp += character;
1150 }
1151
1152 // add the body to the message if it is present
1153 if (hasMessageBody){
1154 httpMessage->GetMessageBody().insert(
1155 httpMessage->GetMessageBody().begin(),
1156 buffer.begin() + bodyStartIndex,
1157 buffer.end()
1158 );
1159 if(httpMessage->GetContentLength() > httpMessage->GetMessageBody().size()){
1160 httpMessage->SetFragmented(true);
1161 }
1162 }
1163
1164 /*
1165 std::cout << "\n\n\n <<<<<<<<<<<<<<<<<<<<<<<<< " << std::string{buffer.begin(), buffer.end()};
1166 std::cout << "content-length:" << httpMessage->GetContentLength() << "\n";
1167 std::cout << "body-length:" << buffer.end() - buffer.begin()+bodyStartIndex << "\n";
1168 std::cout << "body-size:" << httpMessage->GetMessageBody().size() << "\n";
1169 std::cout << "\n\n\n <<<<<<<<<<<<<<<<<<<<<<<<< \n";
1170 */
1171
1172 if(httpMessage->GetContentLength() < httpMessage->GetMessageBody().size()){
1173 httpMessage->GetMessageBody().resize(
1174 httpMessage->GetContentLength()
1175 );
1176 }
1177 }
1178
1179 bool TryExtractHttpMessage(const std::string& bufferStr, std::string& outMessage, size_t& messageSize)
1180 {
1181 size_t headerEnd = bufferStr.find("\r\n\r\n");
1182 if (headerEnd == std::string::npos) {
1183 return false; // Headers not complete yet
1184 }
1185
1186 std::string headerPart = bufferStr.substr(0, headerEnd + 4);
1187 size_t contentLength = 0;
1188
1189 std::istringstream ss(headerPart);
1190 std::string line;
1191 while (std::getline(ss, line)) {
1192 if (line.find("Content-Length:") != std::string::npos) {
1193 try {
1194 contentLength = std::stoi(line.substr(line.find(":") + 1));
1195 } catch (...) {
1196 contentLength = 0;
1197 }
1198 break;
1199 }
1200 }
1201
1202 size_t totalSize = headerEnd + 4 + contentLength;
1203 if (bufferStr.size() < totalSize) {
1204 return false; // Full message not yet available
1205 }
1206
1207 outMessage = bufferStr.substr(0, totalSize);
1209 return true;
1210 }
1211
1212 static bool invalidChar (char c)
1213 {
1214 return !(c>=0 && c <128);
1215 }
1216 void stripUnicode(std::string & str)
1217 {
1218 str.erase(
1219 std::remove_if(str.begin(),str.end(), invalidChar), str.end()
1220 );
1221 }
1222
1223 };
1224
1225
1226} // end of `namespace ns3`
1227
1228
1229#endif /* HTTP_CONTENT_H */
The basic class to represent both HTTP requests and responses.
Definition http.h:77
void SetVersion(const std::string &version)
Set the version of this HTTP message to the string specified.
Definition http.h:580
std::string GetHeader(const std::string &name) const
Get the string value of a single header from the message.
Definition http.h:448
std::string m_path
The path for the resource specified in the message.
Definition http.h:878
uint16_t GetStatusCode() const
Get the status code for this message.
Definition http.h:604
void CreateRequest(const std::string &url, const std::string &method, const std::string &body)
Definition http.h:747
void CreateResponse(const HttpStatus status, const std::string &body)
Definition http.h:790
std::string GetVersion() const
Get the current HTTP version for this message.
Definition http.h:588
std::string GetRequestUri() const
Definition http.h:430
std::string ToString()
Takes the headers added to the message along with the body and outputs it to a std::string for use in...
Definition http.h:632
std::string m_scheme
Definition http.h:880
void SetMethod(const std::string &m)
Set the associated message method for this message.
Definition http.h:463
@ HEAD
Http Method Head.
Definition http.h:84
@ PUT
Http Method Put.
Definition http.h:87
@ PATCH
Http Method Patch.
Definition http.h:85
@ DELETE
Http Method Delete.
Definition http.h:82
@ POST
Http Method Post.
Definition http.h:86
@ GET
Http Method GET.
Definition http.h:83
uint32_t GetSize()
Definition http.h:685
std::string GetMethodToString() const
Definition http.h:486
std::string m_uri
Definition http.h:882
std::string m_version
The version used for this HTTP message as a string.
Definition http.h:890
void CreateResponse(const HttpStatus status, const std::string &body, const std::unordered_map< std::string, std::string > &headers)
Definition http.h:817
std::string GetUri() const
Grab the uri.
Definition http.h:518
void CreateRequest(const std::string &url, const std::string &method)
Definition http.h:735
@ RangeNotSatisfiable
Definition http.h:133
@ VariantAlsoNegotiates
Definition http.h:153
@ NetworkAuthenticationRequired
Definition http.h:157
@ UnavailableForLegalReasons
Definition http.h:145
@ NonAuthoritativeInformation
Definition http.h:100
@ SwitchingProtocol
Definition http.h:93
@ UnsupportedMediaType
Definition http.h:132
@ PreconditionFailed
Definition http.h:129
@ ExpectationFailed
Definition http.h:134
@ RequestHeaderFieldsTooLarge
Definition http.h:144
@ ProxyAuthenticationRequired
Definition http.h:124
@ PermanentRedirect
Definition http.h:115
@ ServiceUnavailable
Definition http.h:150
@ PreconditionRequired
Definition http.h:142
@ TemporaryRedirect
Definition http.h:114
@ InternalServerError
Definition http.h:147
@ UnprocessableEntity
Definition http.h:137
@ HttpVersionNotSupported
Definition http.h:152
@ InsufficientStorage
Definition http.h:154
@ MisdirectedRequest
Definition http.h:136
std::string StatusTextFromStatusCode(const uint16_t statusCode)
To be returned with a status code in a response is a status text describing the status code by text r...
Definition http.h:290
void CreateRequest(const std::string &url, const std::string &method, const std::vector< uint8_t > &body)
Definition http.h:760
uint32_t m_headersLength
Definition http.h:909
std::string GetMessageBodyString()
Definition http.h:713
HTTPMessage & SetHeader(const std::string &name, const std::string &value)
Set a header in the map to the value provided.
Definition http.h:409
std::unordered_map< std::string, std::string > m_headers
An unordered_map of headers using a std::string for both the key and the value.
Definition http.h:896
std::string m_request_uri
Definition http.h:883
std::vector< uint8_t > & GetMessageBody()
Get the body vector for this message.
Definition http.h:708
void SetStatusMessage(const std::string &message)
Set the status message of this HTTP message.
Definition http.h:612
uint16_t m_statusCode
A status code for this message.
Definition http.h:864
std::string m_statusMessage
A status message to be associated with the status code for this message.
Definition http.h:871
std::string GetPath() const
Grab the current associated path of this message.
Definition http.h:572
void CreateResponse(const HttpStatus status, const std::vector< uint8_t > &body)
Definition http.h:800
void SetFragmented(bool value)
Definition http.h:841
HTTPMessage & SetHeaders(const std::unordered_map< std::string, std::string > &headers)
Set a number of headers based on a generic map of keys and values.
Definition http.h:437
void CreateResponse(const HttpStatus status)
Definition http.h:781
std::string m_domain
Definition http.h:881
bool IsFragmented() const
Definition http.h:846
void SetPath(const std::string &url)
Set the path of this message, which will be used if it is a request.
Definition http.h:526
void SetMessageBody(const std::string &body)
Set the body of this message to a string value.
Definition http.h:692
void SetStatusCode(uint16_t code)
Set the status code of this HTTP message.
Definition http.h:596
size_t HeaderCount()
Return the amount of headers in the message.
Definition http.h:730
bool m_fragmented
Whether the payload size is less then content-length.
Definition http.h:906
void SetMessageBody(const std::vector< uint8_t > &body)
Set the body of this message to an unsigned 8-bit binary value.
Definition http.h:700
HTTPMessage::HttpMethod GetMethod() const
Definition http.h:481
uint32_t GetHeadersSize()
Definition http.h:680
std::string GetStatusMessage() const
Get the current status message for this message.
Definition http.h:622
HTTPMessage::HttpMethod m_method
The HTTP method for this message.
Definition http.h:857
size_t GetContentLength() const
Return the size of the binary body vector.
Definition http.h:722
void CreateResponse(const HttpStatus status, const std::vector< uint8_t > &body, const std::unordered_map< std::string, std::string > &headers)
Definition http.h:829
std::vector< uint8_t > m_body
A vector of unsigned 8-bit integers used to store message bodies.
Definition http.h:901
uint32_t m_contentLength
Definition http.h:908
HTTPMessage::HttpStatus GetStatus() const
To be returned with a status code in a response is a status text describing the status code by text r...
Definition http.h:168
A basic class to parse a HTTP message, both request and response.
Definition http.h:936
void Parse(HTTPMessage *httpMessage, const std::string &buffer)
Parse a std::string to a HTTP message.
Definition http.h:946
bool TryExtractHttpMessage(const std::string &bufferStr, std::string &outMessage, size_t &messageSize)
Definition http.h:1179
static bool invalidChar(char c)
Definition http.h:1212
void Parse(HTTPMessage *httpMessage, const std::vector< uint8_t > &buffer)
Parse a binary vector to an HTTP message.
Definition http.h:964
void stripUnicode(std::string &str)
Definition http.h:1216
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Every class exported by the ns3 library is enclosed in the ns3 namespace.
const std::string HTTPVersion1
The string for HTTP version 1.0.
Definition http.h:52
static unsigned int value(char c)
MessageParserState
An enum of states that the HTTPMessageParser can be in.
Definition http.h:917
const std::string CarriageReturn
HTTP defines that any lines must be seperated with a carriage return.
Definition http.h:47
const std::string HTTPVersion11
The string for HTTP version 1.1.
Definition http.h:57