1 /* Copyright Joyent, Inc. and other Node contributors.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to
5  * deal in the Software without restriction, including without limitation the
6  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7  * sell copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19  * IN THE SOFTWARE.
20  */
21 
22 /* Dump what the parser finds to stdout as it happen */
23 
24 #include "http_parser.h"
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 
on_message_begin(http_parser * _)29 int on_message_begin(http_parser* _) {
30   (void)_;
31   printf("\n***MESSAGE BEGIN***\n\n");
32   return 0;
33 }
34 
on_headers_complete(http_parser * _)35 int on_headers_complete(http_parser* _) {
36   (void)_;
37   printf("\n***HEADERS COMPLETE***\n\n");
38   return 0;
39 }
40 
on_message_complete(http_parser * _)41 int on_message_complete(http_parser* _) {
42   (void)_;
43   printf("\n***MESSAGE COMPLETE***\n\n");
44   return 0;
45 }
46 
on_url(http_parser * _,const char * at,size_t length)47 int on_url(http_parser* _, const char* at, size_t length) {
48   (void)_;
49   printf("Url: %.*s\n", (int)length, at);
50   return 0;
51 }
52 
on_header_field(http_parser * _,const char * at,size_t length)53 int on_header_field(http_parser* _, const char* at, size_t length) {
54   (void)_;
55   printf("Header field: %.*s\n", (int)length, at);
56   return 0;
57 }
58 
on_header_value(http_parser * _,const char * at,size_t length)59 int on_header_value(http_parser* _, const char* at, size_t length) {
60   (void)_;
61   printf("Header value: %.*s\n", (int)length, at);
62   return 0;
63 }
64 
on_body(http_parser * _,const char * at,size_t length)65 int on_body(http_parser* _, const char* at, size_t length) {
66   (void)_;
67   printf("Body: %.*s\n", (int)length, at);
68   return 0;
69 }
70 
usage(const char * name)71 void usage(const char* name) {
72   fprintf(stderr,
73           "Usage: %s $type $filename\n"
74           "  type: -x, where x is one of {r,b,q}\n"
75           "  parses file as a Response, reQuest, or Both\n",
76           name);
77   exit(EXIT_FAILURE);
78 }
79 
main(int argc,char * argv[])80 int main(int argc, char* argv[]) {
81   enum http_parser_type file_type;
82 
83   if (argc != 3) {
84     usage(argv[0]);
85   }
86 
87   char* type = argv[1];
88   if (type[0] != '-') {
89     usage(argv[0]);
90   }
91 
92   switch (type[1]) {
93     /* in the case of "-", type[1] will be NUL */
94     case 'r':
95       file_type = HTTP_RESPONSE;
96       break;
97     case 'q':
98       file_type = HTTP_REQUEST;
99       break;
100     case 'b':
101       file_type = HTTP_BOTH;
102       break;
103     default:
104       usage(argv[0]);
105   }
106 
107   char* filename = argv[2];
108   FILE* file = fopen(filename, "r");
109   if (file == NULL) {
110     perror("fopen");
111     goto fail;
112   }
113 
114   fseek(file, 0, SEEK_END);
115   long file_length = ftell(file);
116   if (file_length == -1) {
117     perror("ftell");
118     goto fail;
119   }
120   fseek(file, 0, SEEK_SET);
121 
122   char* data = malloc(file_length);
123   if (fread(data, 1, file_length, file) != (size_t)file_length) {
124     fprintf(stderr, "couldn't read entire file\n");
125     free(data);
126     goto fail;
127   }
128 
129   http_parser_settings settings;
130   memset(&settings, 0, sizeof(settings));
131   settings.on_message_begin = on_message_begin;
132   settings.on_url = on_url;
133   settings.on_header_field = on_header_field;
134   settings.on_header_value = on_header_value;
135   settings.on_headers_complete = on_headers_complete;
136   settings.on_body = on_body;
137   settings.on_message_complete = on_message_complete;
138 
139   http_parser parser;
140   http_parser_init(&parser, file_type);
141   size_t nparsed = http_parser_execute(&parser, &settings, data, file_length);
142   free(data);
143 
144   if (nparsed != (size_t)file_length) {
145     fprintf(stderr,
146             "Error: %s (%s)\n",
147             http_errno_description(HTTP_PARSER_ERRNO(&parser)),
148             http_errno_name(HTTP_PARSER_ERRNO(&parser)));
149     goto fail;
150   }
151 
152   return EXIT_SUCCESS;
153 
154 fail:
155   fclose(file);
156   return EXIT_FAILURE;
157 }
158