Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
pistache
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
pistache
Commits
8335d652
Commit
8335d652
authored
Dec 15, 2015
by
octal
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Started testing the http parser
parent
1dac2f9a
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
221 additions
and
3 deletions
+221
-3
src/http.cc
src/http.cc
+31
-2
src/http.h
src/http.h
+1
-0
src/stream.h
src/stream.h
+1
-1
tests/CMakeLists.txt
tests/CMakeLists.txt
+4
-0
tests/parser_test.cc
tests/parser_test.cc
+184
-0
No files found.
src/http.cc
View file @
8335d652
...
@@ -8,6 +8,7 @@
...
@@ -8,6 +8,7 @@
#include <iostream>
#include <iostream>
#include <stdexcept>
#include <stdexcept>
#include <ctime>
#include <ctime>
#include <cstdio>
#include <iomanip>
#include <iomanip>
#include "common.h"
#include "common.h"
#include "http.h"
#include "http.h"
...
@@ -40,6 +41,31 @@ namespace Private {
...
@@ -40,6 +41,31 @@ namespace Private {
throw
HttpError
(
code
,
msg
);
throw
HttpError
(
code
,
msg
);
}
}
void
Step
::
raiseF
(
Code
code
,
const
char
*
fmt
,
...)
{
struct
VaList
{
VaList
(
va_list
&
args
)
:
args
(
args
)
{
}
~
VaList
()
{
va_end
(
args
);
}
va_list
&
args
;
};
va_list
args
;
va_start
(
args
,
fmt
);
VaList
guard
(
args
);
char
*
v
;
vasprintf
(
&
v
,
fmt
,
args
);
std
::
string
str
(
v
);
free
(
v
);
throw
HttpError
(
code
,
str
);
}
State
State
RequestLineStep
::
apply
(
StreamCursor
&
cursor
)
{
RequestLineStep
::
apply
(
StreamCursor
&
cursor
)
{
StreamCursor
::
Revert
revert
(
cursor
);
StreamCursor
::
Revert
revert
(
cursor
);
...
@@ -70,14 +96,16 @@ namespace Private {
...
@@ -70,14 +96,16 @@ namespace Private {
}
}
if
(
!
found
)
{
if
(
!
found
)
{
raise
(
"Unknown HTTP request method"
);
//raise("Unknown HTTP request method");
return
State
::
Again
;
}
}
int
n
;
int
n
;
if
(
cursor
.
eof
())
return
State
::
Again
;
if
(
cursor
.
eof
())
return
State
::
Again
;
else
if
((
n
=
cursor
.
current
())
!=
' '
)
else
if
((
n
=
cursor
.
current
())
!=
' '
)
raise
(
"Malformed HTTP request after Method, expected SP"
);
raiseF
(
Code
::
Bad_Request
,
"Malformed HTTP request after Method, expected 'SP', got '%c' (0x%d)"
,
n
,
n
);
if
(
!
cursor
.
advance
(
1
))
return
State
::
Again
;
if
(
!
cursor
.
advance
(
1
))
return
State
::
Again
;
...
@@ -125,6 +153,7 @@ namespace Private {
...
@@ -125,6 +153,7 @@ namespace Private {
const
char
*
ver
=
versionToken
.
rawText
();
const
char
*
ver
=
versionToken
.
rawText
();
const
size_t
size
=
versionToken
.
size
();
const
size_t
size
=
versionToken
.
size
();
if
(
strncmp
(
ver
,
"HTTP/1.0"
,
size
)
==
0
)
{
if
(
strncmp
(
ver
,
"HTTP/1.0"
,
size
)
==
0
)
{
request
->
version_
=
Version
::
Http10
;
request
->
version_
=
Version
::
Http10
;
}
}
...
...
src/http.h
View file @
8335d652
...
@@ -406,6 +406,7 @@ namespace Private {
...
@@ -406,6 +406,7 @@ namespace Private {
virtual
State
apply
(
StreamCursor
&
cursor
)
=
0
;
virtual
State
apply
(
StreamCursor
&
cursor
)
=
0
;
void
raise
(
const
char
*
msg
,
Code
code
=
Code
::
Bad_Request
);
void
raise
(
const
char
*
msg
,
Code
code
=
Code
::
Bad_Request
);
void
raiseF
(
Code
code
,
const
char
*
msg
,
...);
Request
*
request
;
Request
*
request
;
};
};
...
...
src/stream.h
View file @
8335d652
...
@@ -97,7 +97,7 @@ public:
...
@@ -97,7 +97,7 @@ public:
}
}
memcpy
(
bytes
+
size
,
data
,
len
);
memcpy
(
bytes
+
size
,
data
,
len
);
Base
::
setg
(
bytes
,
bytes
+
size
,
bytes
+
size
+
len
);
Base
::
setg
(
bytes
,
this
->
gptr
()
,
bytes
+
size
+
len
);
size
+=
len
;
size
+=
len
;
return
true
;
return
true
;
}
}
...
...
tests/CMakeLists.txt
View file @
8335d652
...
@@ -13,3 +13,7 @@ add_test( async_test run_async_test )
...
@@ -13,3 +13,7 @@ add_test( async_test run_async_test )
add_executable
(
run_typeid_test typeid_test.cc
)
add_executable
(
run_typeid_test typeid_test.cc
)
target_link_libraries
(
run_typeid_test gtest gtest_main
)
target_link_libraries
(
run_typeid_test gtest gtest_main
)
add_test
(
typeid_test run_typeid_test
)
add_test
(
typeid_test run_typeid_test
)
add_executable
(
run_parser_test parser_test.cc
)
target_link_libraries
(
run_parser_test gtest gtest_main net
)
add_test
(
parser_test run_parser_test
)
tests/parser_test.cc
0 → 100644
View file @
8335d652
#include "gtest/gtest.h"
#include "http.h"
#include <algorithm>
#include <string>
using
namespace
Net
;
using
namespace
Net
::
Http
;
class
TestScenario
{
public:
TestScenario
&
recvData
(
const
char
*
data
)
{
buf
+=
data
;
return
*
this
;
}
TestScenario
&
exception
()
{
entries
.
push_back
(
makeEntry
<
Exception
>
());
return
*
this
;
}
TestScenario
&
yield
()
{
entries
.
push_back
(
makeEntry
<
Yield
>
());
return
*
this
;
}
TestScenario
&
method
(
Http
::
Method
meth
)
{
entries
.
push_back
(
makeEntry
<
Method
>
(
meth
));
return
*
this
;
}
TestScenario
&
resource
(
const
std
::
string
&
res
)
{
entries
.
push_back
(
makeEntry
<
Resource
>
(
res
));
return
*
this
;
}
TestScenario
&
version
(
Http
::
Version
ver
)
{
entries
.
push_back
(
makeEntry
<
Version
>
(
ver
));
return
*
this
;
}
TestScenario
&
crlf
()
{
buf
.
append
(
{
0xD
,
0xA
}
);
return
*
this
;
}
void
run
()
{
for
(
const
auto
&
entry
:
entries
)
{
entry
.
element
->
feed
(
parser
,
entry
.
data
);
entry
.
element
->
check
(
parser
);
}
}
private:
struct
Element
{
virtual
void
feed
(
Private
::
Parser
&
parser
,
const
std
::
string
&
data
)
const
{
parser
.
feed
(
data
.
c_str
(),
data
.
size
());
parser
.
parse
();
}
virtual
void
check
(
Private
::
Parser
&
parser
)
const
=
0
;
};
struct
Entry
{
std
::
string
data
;
std
::
unique_ptr
<
Element
>
element
;
};
struct
Exception
:
public
Element
{
virtual
void
feed
(
Private
::
Parser
&
parser
,
const
std
::
string
&
data
)
const
{
parser
.
feed
(
data
.
c_str
(),
data
.
size
());
ASSERT_THROW
(
parser
.
parse
(),
HttpError
);
}
void
check
(
Private
::
Parser
&
parser
)
const
{
}
};
struct
Yield
:
public
Element
{
void
feed
(
Private
::
Parser
&
parser
,
const
std
::
string
&
data
)
const
{
parser
.
feed
(
data
.
c_str
(),
data
.
size
());
ASSERT_EQ
(
parser
.
parse
(),
Private
::
State
::
Again
);
}
void
check
(
Private
::
Parser
&
parser
)
const
{
}
};
struct
Method
:
public
Element
{
Method
(
Http
::
Method
method
)
:
method_
(
method
)
{
}
void
check
(
Private
::
Parser
&
parser
)
const
{
ASSERT_EQ
(
parser
.
request
.
method
(),
method_
);
}
private:
Http
::
Method
method_
;
};
struct
Resource
:
public
Element
{
Resource
(
const
std
::
string
&
resource
)
:
resource_
(
resource
)
{
}
void
check
(
Private
::
Parser
&
parser
)
const
{
ASSERT_EQ
(
parser
.
request
.
resource
(),
resource_
);
}
private:
std
::
string
resource_
;
};
struct
Version
:
public
Element
{
Version
(
Http
::
Version
version
)
:
version_
(
version
)
{
}
void
check
(
Private
::
Parser
&
parser
)
const
{
ASSERT_EQ
(
parser
.
request
.
version
(),
version_
);
}
private:
Http
::
Version
version_
;
};
template
<
typename
E
,
typename
...
Args
>
Entry
makeEntry
(
Args
&&
...
args
)
{
Entry
entry
;
entry
.
data
=
buf
;
entry
.
element
.
reset
(
new
E
(
std
::
forward
<
Args
>
(
args
)...));
buf
.
clear
();
return
entry
;
}
std
::
vector
<
Entry
>
entries
;
Private
::
Parser
parser
;
std
::
string
buf
;
};
TEST
(
parser_test
,
test_http_parsing
)
{
TestScenario
scenario1
;
scenario1
.
recvData
(
"GET"
).
method
(
Method
::
Get
)
.
recvData
(
" /foo "
).
resource
(
"/foo"
)
.
recvData
(
"HTTP/1.1"
).
crlf
().
version
(
Version
::
Http11
);
scenario1
.
run
();
TestScenario
scenario2
;
scenario2
.
recvData
(
"GE"
).
yield
()
.
recvData
(
"T"
).
method
(
Method
::
Get
)
.
recvData
(
" "
).
yield
()
.
recvData
(
"/foo"
).
yield
()
.
recvData
(
"Index"
).
yield
()
.
recvData
(
" "
).
resource
(
"/fooIndex"
)
.
recvData
(
"HT"
).
yield
()
.
recvData
(
"TP/"
).
yield
()
.
recvData
(
"1.1"
).
crlf
().
version
(
Version
::
Http11
);
scenario2
.
run
();
TestScenario
scenario3
;
scenario3
.
recvData
(
"POST"
).
method
(
Method
::
Post
)
.
recvData
(
"-"
).
exception
();
scenario3
.
run
();
TestScenario
scenario4
;
scenario4
.
recvData
(
"PUT"
).
method
(
Method
::
Put
)
.
recvData
(
" / "
).
resource
(
"/"
)
.
recvData
(
"H"
).
yield
()
.
recvData
(
"T"
).
yield
()
.
recvData
(
"T"
).
yield
()
.
recvData
(
"P"
).
yield
()
.
recvData
(
"/1.0"
).
crlf
().
version
(
Version
::
Http10
);
scenario4
.
run
();
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment