Squid Web Cache
master
Loading...
Searching...
No Matches
StatusLine.cc
Go to the documentation of this file.
1
/*
2
* Copyright (C) 1996-2025 The Squid Software Foundation and contributors
3
*
4
* Squid software is distributed under GPLv2+ license and includes
5
* contributions from numerous individuals and organizations.
6
* Please see the COPYING and CONTRIBUTORS files for details.
7
*/
8
9
/* DEBUG: section 57 HTTP Status-line */
10
11
#include "
squid.h
"
12
#include "
base/Packable.h
"
13
#include "
debug/Stream.h
"
14
#include "
http/one/ResponseParser.h
"
15
#include "
http/StatusLine.h
"
16
#include "
parser/forward.h
"
17
#include "
parser/Tokenizer.h
"
18
19
#include <algorithm>
20
21
void
22
Http::StatusLine::init
()
23
{
24
set
(
Http::ProtocolVersion
(),
Http::scNone
,
nullptr
);
25
}
26
27
void
28
Http::StatusLine::clean
()
29
{
30
set(
Http::ProtocolVersion
(),
Http::scInternalServerError
,
nullptr
);
31
}
32
33
/* set values */
34
void
35
Http::StatusLine::set
(
const
AnyP::ProtocolVersion
&newVersion,
const
Http::StatusCode
newStatus,
const
char
*newReason)
36
{
37
version
= newVersion;
38
status_ = newStatus;
39
/* Note: no xstrdup for 'reason', assumes constant 'reasons' */
40
reason_ = newReason;
41
}
42
43
const
char
*
44
Http::StatusLine::reason
()
const
45
{
46
return
reason_ ? reason_ :
Http::StatusCodeString
(status());
47
}
48
49
size_t
50
Http::StatusLine::packedLength
()
const
51
{
52
// Keep in sync with packInto(). TODO: Refactor to avoid code duplication.
53
54
auto
packedStatus = status();
55
auto
packedReason = reason();
56
57
if
(packedStatus ==
scNone
) {
58
packedStatus =
scInternalServerError
;
59
packedReason =
StatusCodeString
(packedStatus);
60
}
61
62
// "ICY %3d %s\r\n"
63
if
(
version
.protocol ==
AnyP::PROTO_ICY
) {
64
return
65
+ 3
// ICY
66
+ 1
// SP
67
+ 3
// %3d (packedStatus)
68
+ 1
// SP
69
+ strlen(packedReason)
// %s
70
+ 2;
// CRLF
71
}
72
73
// "HTTP/%d.%d %3d %s\r\n"
74
return
75
+ 4
// HTTP
76
+ 1
// "/"
77
+ 3
// %d.%d (version.major and version.minor)
78
+ 1
// SP
79
+ 3
// %3d (packedStatus)
80
+ 1
// SP
81
+ strlen(packedReason)
// %s
82
+ 2;
// CRLF
83
}
84
85
void
86
Http::StatusLine::packInto
(
Packable
* p)
const
87
{
88
// Keep in sync with packedLength().
89
90
assert
(p);
91
92
auto
packedStatus = status();
93
auto
packedReason = reason();
94
95
if
(packedStatus ==
Http::scNone
) {
96
static
unsigned
int
reports = 0;
97
if
(++reports <= 100)
98
debugs
(57,
DBG_IMPORTANT
,
"ERROR: Squid BUG: the internalized response lacks status-code"
);
99
packedStatus =
Http::scInternalServerError
;
100
packedReason =
Http::StatusCodeString
(packedStatus);
// ignore custom reason_ (if any)
101
}
102
103
/* local constants */
104
/* AYJ: see bug 2469 - RFC2616 confirms stating 'SP characters' plural! */
105
static
const
char
*Http1StatusLineFormat =
"HTTP/%d.%d %3d %s\r\n"
;
106
static
const
char
*IcyStatusLineFormat =
"ICY %3d %s\r\n"
;
107
108
/* handle ICY protocol status line specially. Pass on the bad format. */
109
if
(
version
.protocol ==
AnyP::PROTO_ICY
) {
110
debugs
(57, 9,
"packing sline "
<<
this
<<
" using "
<< p <<
":"
);
111
debugs
(57, 9,
"FORMAT="
<< IcyStatusLineFormat );
112
debugs
(57, 9,
"ICY "
<< packedStatus <<
" "
<< packedReason);
113
p->
appendf
(IcyStatusLineFormat, packedStatus, packedReason);
114
return
;
115
}
116
117
debugs
(57, 9,
"packing sline "
<<
this
<<
" using "
<< p <<
":"
);
118
debugs
(57, 9,
"FORMAT="
<< Http1StatusLineFormat );
119
debugs
(57, 9,
"HTTP/"
<<
version
.major <<
"."
<<
version
.minor <<
" "
<< packedStatus <<
" "
<< packedReason);
120
p->
appendf
(Http1StatusLineFormat,
version
.major,
version
.minor, packedStatus, packedReason);
121
}
122
123
bool
124
Http::StatusLine::parse
(
const
String
&protoPrefix,
const
char
*start,
const
char
*end)
125
{
126
status_ =
Http::scInvalidHeader
;
/* Squid header parsing error */
127
128
// XXX: Http::Message::parse() has a similar check but is using
129
// casesensitive comparison (which is required by HTTP errata?)
130
131
if
(protoPrefix.
cmp
(
"ICY"
, 3) == 0) {
132
debugs
(57, 3,
"Invalid HTTP identifier. Detected ICY protocol instead."
);
133
version
=
AnyP::ProtocolVersion
(
AnyP::PROTO_ICY
, 1, 0);
134
start += protoPrefix.
size
();
135
}
else
if
(protoPrefix.
caseCmp
(start, protoPrefix.
size
()) == 0) {
136
137
start += protoPrefix.
size
();
138
139
if
(!
xisdigit
(*start))
140
return
false
;
141
142
// XXX: HTTPbis have defined this to be single-digit version numbers. no need to sscanf()
143
// XXX: furthermore, only HTTP/1 will be using ASCII format digits
144
145
if
(sscanf(start,
"%d.%d"
, &
version
.major, &
version
.minor) != 2) {
146
debugs
(57, 7,
"Invalid HTTP identifier."
);
147
return
false
;
148
}
149
}
else
150
return
false
;
151
152
if
(!(start = strchr(start,
' '
)))
153
return
false
;
154
155
++start;
// skip SP between HTTP-version and status-code
156
157
assert
(start <= end);
158
const
auto
stdStatusAreaLength = 4;
// status-code length plus SP
159
const
auto
unparsedLength = end - start;
160
const
auto
statusAreaLength = std::min<size_t>(stdStatusAreaLength, unparsedLength);
161
162
static
SBuf
statusBuf;
163
statusBuf.
assign
(start, statusAreaLength);
164
Parser::Tokenizer
tok
(statusBuf);
165
try
{
166
One::ResponseParser::ParseResponseStatus
(
tok
, status_);
167
}
catch
(
const
Parser::InsufficientInput
&) {
168
debugs
(57, 7,
"need more; have "
<< unparsedLength);
169
return
false
;
170
}
catch
(...) {
171
debugs
(57, 3,
"cannot parse status-code area: "
<<
CurrentException
);
172
return
false
;
173
}
174
175
// XXX check if the given 'reason' is the default status string, if not save to reason_
176
177
/* we ignore 'reason-phrase' */
178
/* Should assert start < end ? */
179
return
true
;
/* success */
180
}
181
Packable.h
ResponseParser.h
StatusLine.h
CurrentException
std::ostream & CurrentException(std::ostream &os)
prints active (i.e., thrown but not yet handled) exception
Definition
TextException.cc:88
assert
#define assert(EX)
Definition
assert.h:17
version
static int version
Definition
basic_ldap_auth.cc:166
AnyP::ProtocolVersion
Definition
ProtocolVersion.h:24
Http::One::ResponseParser::ParseResponseStatus
static void ParseResponseStatus(Tokenizer &, StatusCode &code)
Definition
ResponseParser.cc:86
Http::StatusLine::parse
bool parse(const String &protoPrefix, const char *start, const char *end)
Definition
StatusLine.cc:124
Http::StatusLine::init
void init()
reset this status-line back to empty state
Definition
StatusLine.cc:22
Http::StatusLine::clean
void clean()
reset this status-line back to Internal Server Error state
Definition
StatusLine.cc:28
Http::StatusLine::packedLength
size_t packedLength() const
expected size of packInto() output
Definition
StatusLine.cc:50
Http::StatusLine::packInto
void packInto(Packable *) const
pack fields into a Packable object
Definition
StatusLine.cc:86
Http::StatusLine::set
void set(const AnyP::ProtocolVersion &newVersion, Http::StatusCode newStatus, const char *newReason=nullptr)
Definition
StatusLine.cc:35
Http::StatusLine::reason
const char * reason() const
retrieve the reason string for this status line
Definition
StatusLine.cc:44
Packable
Definition
Packable.h:53
Packable::appendf
void appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Append operation with printf-style arguments.
Definition
Packable.h:61
Parser::InsufficientInput
thrown by modern "incremental" parsers when they need more data
Definition
forward.h:18
Parser::Tokenizer
Definition
Tokenizer.h:30
SBuf
Definition
SBuf.h:94
SBuf::assign
SBuf & assign(const SBuf &S)
Definition
SBuf.cc:83
String
Definition
SquidString.h:27
String::cmp
int cmp(char const *) const
Definition
String.cc:243
String::caseCmp
int caseCmp(char const *) const
Definition
String.cc:273
String::size
size_type size() const
Definition
SquidString.h:74
Stream.h
DBG_IMPORTANT
#define DBG_IMPORTANT
Definition
Stream.h:38
debugs
#define debugs(SECTION, LEVEL, CONTENT)
Definition
Stream.h:192
AnyP::PROTO_ICY
@ PROTO_ICY
Definition
ProtocolType.h:37
Http::StatusCode
StatusCode
Definition
StatusCode.h:20
Http::scInternalServerError
@ scInternalServerError
Definition
StatusCode.h:73
Http::scInvalidHeader
@ scInvalidHeader
Squid header parsing error.
Definition
StatusCode.h:88
Http::scNone
@ scNone
Definition
StatusCode.h:21
Http::ProtocolVersion
AnyP::ProtocolVersion ProtocolVersion()
Definition
ProtocolVersion.h:32
Http::StatusCodeString
const char * StatusCodeString(const Http::StatusCode status)
Definition
StatusCode.cc:15
Tokenizer.h
forward.h
squid.h
tok
Definition
parse.c:160
xisdigit
#define xisdigit(x)
Definition
xis.h:18
squid
src
http
StatusLine.cc
Generated by
1.9.8