python: add Session.submit_headers()

This commit is contained in:
Tatsuhiro Tsujikawa 2012-08-22 01:41:07 +09:00
parent 7580c9f671
commit 7a362e23b3
4 changed files with 89 additions and 1 deletions

View File

@ -384,6 +384,28 @@ Session objects
The :py:class:`InvalidArgumentError` will be raised if the *nv*
includes empty name or ``None`` value.
.. py:method:: Session.submit_headers(flags, stream_id, nv)
Submits HEADERS frame. The *flags* is bitwise OR of the following
values:
* :py:const:`CTRL_FLAG_FIN`
If *flags* includes :py:const:`CTRL_FLAG_FIN`, this frame has
FLAG_FIN flag set.
The stream which this frame belongs to is given in the
*stream_id*. The *nv* is the name/value pairs in this frame.
The *nv* is a list containing the name/value pairs. The each
element is a tuple of 2 bytestrings: name and value (e.g.,
``(b'host', b'localhost')``).
The names in *nv* will be lower-cased when they are sent.
The :py:class:`InvalidArgumentError` will be raised if the *nv*
includes empty name or ``None`` value.
.. py:method:: Session.submit_data(stream_id, flags, data_prd)
Submits one or more DATA frames to the stream *stream_id*. The

View File

@ -99,6 +99,11 @@ cdef extern from 'spdylay/spdylay.h':
int32_t stream_id
char **nv
ctypedef struct spdylay_headers:
spdylay_ctrl_hd hd
int32_t stream_id
char **nv
ctypedef struct spdylay_rst_stream:
spdylay_ctrl_hd hd
int32_t stream_id
@ -126,7 +131,7 @@ cdef extern from 'spdylay/spdylay.h':
spdylay_settings settings
#spdylay_ping ping
spdylay_goaway goaway
#spdylay_headers headers
spdylay_headers headers
#spdylay_window_update window_update
#spdylay_credential credential
@ -233,6 +238,9 @@ cdef extern from 'spdylay/spdylay.h':
int spdylay_submit_syn_reply(spdylay_session *session, uint8_t flags,
int32_t stream_id, char **nv)
int spdylay_submit_headers(spdylay_session *session, uint8_t flags,
int32_t stream_id, char **nv)
int spdylay_submit_data(spdylay_session *session, int32_t stream_id,
uint8_t flags, spdylay_data_provider *data_prd)

View File

@ -104,6 +104,24 @@ cdef class SynReplyFrame(CtrlFrame):
def __get__(self):
return self.nv
cdef class HeadersFrame(CtrlFrame):
cdef int32_t stream_id
cdef object nv
cdef void fill(self, cspdylay.spdylay_headers *frame):
self.fillhd(&frame.hd)
self.stream_id = frame.stream_id
self.nv = cnv2pynv(frame.nv)
property stream_id:
def __get__(self):
return self.stream_id
property nv:
def __get__(self):
return self.nv
cdef class RstStreamFrame(CtrlFrame):
cdef int32_t stream_id
cdef uint32_t status_code
@ -218,6 +236,7 @@ cdef void on_ctrl_recv_callback(cspdylay.spdylay_session *session,
void *user_data):
cdef SynStreamFrame syn_stream
cdef SynReplyFrame syn_reply
cdef HeadersFrame headers
cdef RstStreamFrame rst_stream
cdef SettingsFrame settings
cdef GoawayFrame goaway
@ -236,6 +255,10 @@ cdef void on_ctrl_recv_callback(cspdylay.spdylay_session *session,
syn_reply = SynReplyFrame()
syn_reply.fill(&frame.syn_reply)
pyframe = syn_reply
elif frame_type == cspdylay.SPDYLAY_HEADERS:
headers = HeadersFrame()
headers.fill(&frame.headers)
pyframe = headers
elif frame_type == cspdylay.SPDYLAY_RST_STREAM:
rst_stream = RstStreamFrame()
rst_stream.fill(&frame.rst_stream)
@ -644,6 +667,19 @@ cdef class Session:
elif rv == cspdylay.SPDYLAY_ERR_NOMEM:
raise MemoryError()
cpdef submit_headers(self, flags, stream_id, nv):
cdef char **cnv = pynv2cnv(nv)
cdef int rv
rv = cspdylay.spdylay_submit_headers(self._c_session,
flags, stream_id, cnv)
free(cnv)
if rv == 0:
return
elif rv == cspdylay.SPDYLAY_ERR_INVALID_ARGUMENT:
raise InvalidArgumentError(cspdylay.spdylay_strerror(rv))
elif rv == cspdylay.SPDYLAY_ERR_NOMEM:
raise MemoryError()
cpdef submit_data(self, stream_id, flags, data_prd):
cdef cspdylay.spdylay_data_provider c_data_prd
cdef cspdylay.spdylay_data_provider *c_data_prd_ptr

View File

@ -282,5 +282,27 @@ class SpdylayTests(unittest.TestCase):
self.assertEqual(b'Hello World',
self.server_streams.recv_data.getvalue())
def test_submit_headers(self):
self.client_session.submit_syn_stream(spdylay.CTRL_FLAG_NONE, 0, 2,
[(b':path', b'/')], None)
self.client_session.send()
self.server_session.recv()
self.assertEqual(1, len(self.server_streams.recv_frames))
frame = self.server_streams.recv_frames[0]
self.assertEqual(spdylay.SYN_STREAM, frame.frame_type)
self.assertEqual(1, frame.stream_id)
self.client_session.submit_headers(spdylay.CTRL_FLAG_FIN, 1,
[(b':host', b'localhost')])
self.client_session.send()
self.server_session.recv()
self.assertEqual(2, len(self.server_streams.recv_frames))
frame = self.server_streams.recv_frames[1]
self.assertEqual(spdylay.HEADERS, frame.frame_type)
self.assertEqual(1, frame.stream_id)
self.assertEqual((b':host', b'localhost'), frame.nv[0])
if __name__ == '__main__':
unittest.main()