comparison http_request.t @ 1955:0b1a671c20c1

Tests: basic request parsing tests.
author Maxim Dounin <mdounin@mdounin.ru>
date Sat, 30 Mar 2024 07:49:05 +0300
parents
children 4e79bd25642f
comparison
equal deleted inserted replaced
1954:5cf0e07d63a1 1955:0b1a671c20c1
1 #!/usr/bin/perl
2
3 # (C) Maxim Dounin
4
5 # Tests for basic HTTP request parsing.
6
7 ###############################################################################
8
9 use warnings;
10 use strict;
11
12 use Test::More;
13
14 use Socket qw/ CRLF CR LF /;
15
16 BEGIN { use FindBin; chdir($FindBin::Bin); }
17
18 use lib 'lib';
19 use Test::Nginx;
20
21 ###############################################################################
22
23 select STDERR; $| = 1;
24 select STDOUT; $| = 1;
25
26 my $t = Test::Nginx->new()->has(qw/http rewrite/)->plan(40)
27 ->write_file_expand('nginx.conf', <<'EOF');
28
29 %%TEST_GLOBALS%%
30
31 daemon off;
32
33 events {
34 }
35
36 http {
37 %%TEST_GLOBALS_HTTP%%
38
39 server {
40 listen 127.0.0.1:8080;
41 return 200 ok\n;
42 }
43 }
44
45 EOF
46
47 $t->run();
48
49 ###############################################################################
50
51 # some basic HTTP/0.9, HTTP/1.0, and HTTP/1.1 requests
52
53 like(http(
54 "GET /" . CRLF
55 ), qr/^ok/s, 'http/0.9 request');
56
57 like(http(
58 "GET / HTTP/1.0" . CRLF .
59 CRLF
60 ), qr/ 200 /, 'http/1.0 request');
61
62 like(http(
63 "GET / HTTP/1.0" . CRLF .
64 "Host: foo" . CRLF .
65 CRLF
66 ), qr/ 200 /, 'http/1.0 request with host');
67
68 like(http(
69 "GET / HTTP/1.1" . CRLF .
70 "Host: foo" . CRLF .
71 "Connection: close" . CRLF .
72 CRLF
73 ), qr/ 200 /, 'http/1.1 request');
74
75 like(http(
76 "GET / HTTP/1.1" . CRLF .
77 "Connection: close" . CRLF .
78 CRLF
79 ), qr/ 400 /, 'http/1.1 request rejected without host');
80
81 like(http(
82 "GET http://foo/ HTTP/1.1" . CRLF .
83 "Host: foo" . CRLF .
84 "Connection: close" . CRLF .
85 CRLF
86 ), qr/ 200 /, 'http/1.1 request absolute form');
87
88 # ensure an empty line is ignored before the request
89
90 like(http(CRLF . "GET / HTTP/1.0" . CRLF . CRLF), qr/ 200 /,
91 'empty line ignored');
92 like(http(LF . "GET / HTTP/1.0" . CRLF . CRLF), qr/ 200 /,
93 'empty line with just LF ignored');
94
95 TODO: {
96 local $TODO = 'not yet' unless $t->has_version('1.25.5');
97
98 like(http(CR . "GET / HTTP/1.0" . CRLF . CRLF), qr/ 400 /,
99 'empty line with just CR rejected');
100 like(http(CRLF . CRLF . "GET / HTTP/1.0" . CRLF . CRLF), qr/ 400 /,
101 'multiple empty lines rejected');
102 like(http(LF . LF . "GET / HTTP/1.0" . CRLF . CRLF), qr/ 400 /,
103 'multiple LFs rejected');
104 like(http(CR . CR . "GET / HTTP/1.0" . CRLF . CRLF), qr/ 400 /,
105 'multiple CRs rejected');
106
107 }
108
109 # method
110
111 like(http("FOO / HTTP/1.0" . CRLF . CRLF), qr/ 200 /, 'method');
112 like(http("FOO-BAR / HTTP/1.0" . CRLF . CRLF), qr/ 200 /,
113 'method with dash');
114 like(http("FOO_BAR / HTTP/1.0" . CRLF . CRLF), qr/ 200 /,
115 'method with underscore');
116 like(http("FOO.BAR / HTTP/1.0" . CRLF . CRLF), qr/ 400 /,
117 'method with dot rejected');
118 like(http("get / HTTP/1.0" . CRLF . CRLF), qr/ 400 /,
119 'method in lowercase rejected');
120
121 # URI
122
123 like(http("GET /foo12.bar HTTP/1.0" . CRLF . CRLF), qr/ 200 /, 'uri');
124 like(http("GET /control\x0d HTTP/1.0" . CRLF . CRLF), qr/ 400 /,
125 'uri with CR');
126 like(http("GET /control\x01 HTTP/1.0" . CRLF . CRLF), qr/ 400 /,
127 'uri with control');
128 like(http("GET /control\t HTTP/1.0" . CRLF . CRLF), qr/ 400 /,
129 'uri with tab');
130
131 # version
132
133 like(http(
134 "GET / HTTP/1.2" . CRLF .
135 "Host: foo" . CRLF .
136 "Connection: close" . CRLF .
137 CRLF
138 ), qr/ 200 /, 'version 1.2');
139
140 like(http(
141 "GET / HTTP/1.99" . CRLF .
142 "Host: foo" . CRLF .
143 "Connection: close" . CRLF .
144 CRLF
145 ), qr/ 200 /, 'version 1.99');
146
147 like(http("GET / HTTP/1.000" . CRLF . CRLF), qr/ 200 /,
148 'version leading zeros');
149 like(http("GET / HTTP/2.0" . CRLF . CRLF), qr/ 505 /,
150 'version too high rejected');
151 like(http("GET / HTTP/1.x" . CRLF . CRLF), qr/ 400 /,
152 'version non-numeric rejected');
153 like(http("GET / HTTP/1.100" . CRLF . CRLF), qr/ 400 /,
154 'version too high minor rejected');
155
156 like(http("GET / http/1.0" . CRLF . CRLF), qr/ 400 /,
157 'lowercase protocol rejected');
158
159 # spaces in request line
160
161 like(http("GET / HTTP/1.0 " . CRLF . CRLF), qr/ 200 /,
162 'spaces after version');
163 like(http("GET / HTTP/1.0" . CRLF . CRLF), qr/ 200 /,
164 'spaces after uri');
165 like(http("GET / HTTP/1.0" . CRLF . CRLF), qr/ 200 /,
166 'spaces before uri');
167
168 like(http("GET / HTTP/ 1.0" . CRLF . CRLF), qr/ 400 /,
169 'spaces before version rejected');
170 like(http("GET / HTTP /1.0" . CRLF . CRLF), qr/ 400 /,
171 'spaces after protocol rejected');
172 like(http("GET / HT TP/1.0" . CRLF . CRLF), qr/ 400 /,
173 'spaces within protocol rejected');
174 like(http(" GET / HTTP/ 1.0" . CRLF . CRLF), qr/ 400 /,
175 'spaces before method rejected');
176
177 # headers
178
179 like(http("GET / HTTP/1.0" . CRLF . "Foo: bar" . CRLF . CRLF), qr/ 200 /,
180 'header');
181 like(http("GET / HTTP/1.0" . CRLF . "Foo : bar" . CRLF . CRLF), qr/ 400 /,
182 'header with space rejected');
183 like(http("GET / HTTP/1.0" . CRLF . " Foo: bar" . CRLF . CRLF), qr/ 400 /,
184 'header with leading space rejected');
185 like(http("GET / HTTP/1.0" . CRLF . "Foo\x01: bar" . CRLF . CRLF), qr/ 400 /,
186 'header with control rejected');
187 like(http("GET / HTTP/1.0" . CRLF . "Foo\t: bar" . CRLF . CRLF), qr/ 400 /,
188 'header with tab rejected');
189
190 ###############################################################################